mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-01 18:50:16 +03:00
Create unit-test windows hidden from the start while preserving hardware OpenGL rendering. Force double buffering for hidden X11 windows so framebuffer capture reads the rendered back buffer reliably, and keep SDL2/SDL3 behavior consistent. Update unit-test documentation to use direct desktop execution by default, with Xvfb retained for headless environments.
This change might break unit-tests in other platforms, next CI run will let us know.
This commit is contained in:
+24
-14
@@ -7,23 +7,33 @@ The test binary manages its own current working directory, so you can execute it
|
||||
|
||||
* **Prefer the release test binary during normal development:**
|
||||
When AddressSanitizer or other debug-only diagnostics are not required, build and run `bin/unit_tests/eepp-unit_tests`. The optimized release suite is substantially faster and should be the default for iterative testing. Use `bin/unit_tests/eepp-unit_tests-debug` when investigating memory safety, assertions, or other behavior that specifically requires the debug configuration.
|
||||
* **Default Execution for Agents on Linux & FreeBSD:**
|
||||
Always run unit tests through the project wrapper unless the user explicitly asks for a different harness:
|
||||
`projects/scripts/xvfb-run-eepp bin/unit_tests/eepp-unit_tests`
|
||||
* **Why the wrapper is required:**
|
||||
Tests open ~400 individual windows. The wrapper runs them in an isolated framebuffer, enables race-safe automatic display selection for concurrent agent test runs, sets the default screen to `1280x1024x24`, and injects `ASAN_OPTIONS=detect_leaks=0` automatically.
|
||||
* **Do not skip the wrapper for filtered tests:**
|
||||
A focused test still needs the same wrapper:
|
||||
`projects/scripts/xvfb-run-eepp bin/unit_tests/eepp-unit_tests --filter="FontRendering.*Offset*"`
|
||||
* **Fallback only when the wrapper itself fails:**
|
||||
If `projects/scripts/xvfb-run-eepp` fails before launching the test binary, report that wrapper failure and then use this fallback to keep verification moving:
|
||||
`xvfb-run -a -s "-screen 0 1280x1024x24" bin/unit_tests/eepp-unit_tests`
|
||||
Do not use plain `xvfb-run` as the first attempt for GUI/unit tests.
|
||||
* **Direct Execution (Only for non-window tests or explicit user requests):**
|
||||
* **Default Execution on a Graphical Linux Desktop:**
|
||||
Unit-test windows are created hidden, so run the release suite directly against the desktop:
|
||||
`bin/unit_tests/eepp-unit_tests`
|
||||
This keeps the windows invisible and unfocused while preserving hardware OpenGL acceleration.
|
||||
Confirm that the renderer log names the real GPU rather than llvmpipe when validating rendering
|
||||
behavior or performance.
|
||||
* **Filtered Tests on a Graphical Linux Desktop:**
|
||||
Use the same direct hardware-backed command for focused runs:
|
||||
`bin/unit_tests/eepp-unit_tests --filter="FontRendering.*Offset*"`
|
||||
* **Headless CI and Systems Without a Usable Desktop Display:**
|
||||
Keep `projects/scripts/xvfb-run-eepp` as the fallback when no desktop display is available:
|
||||
`projects/scripts/xvfb-run-eepp bin/unit_tests/eepp-unit_tests`
|
||||
The wrapper provides a race-safe isolated display at `1280x1024x24` and injects
|
||||
`ASAN_OPTIONS=detect_leaks=0`. Xvfb can use llvmpipe, so do not use wrapper timings to evaluate
|
||||
hardware-rendered performance.
|
||||
* **Wrapper Fallback:**
|
||||
If `projects/scripts/xvfb-run-eepp` itself fails before launching the test binary, report that
|
||||
failure and use:
|
||||
`xvfb-run -a -s "-screen 0 1280x1024x24" bin/unit_tests/eepp-unit_tests`
|
||||
Do not use plain `xvfb-run` as the first headless attempt.
|
||||
* **Non-window Tests:**
|
||||
Tests known not to create windows can run without selecting a video driver:
|
||||
`bin/unit_tests/eepp-unit_tests --filter="NonWindowTest.*"`
|
||||
* **Filtering Tests:**
|
||||
Use the `--filter` parameter to run specific tests (supports glob patterns).
|
||||
Keep the wrapper in front of the binary unless the test is known not to create windows.
|
||||
Keep the same harness as the full suite: direct execution on a graphical Linux desktop, or the
|
||||
wrapper in a genuinely headless environment.
|
||||
|
||||
## Writing New Tests
|
||||
Writing new tests is highly encouraged, but depends on the context of your changes:
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
#include <eepp/config.hpp>
|
||||
#include <string>
|
||||
|
||||
#define EEPP_MAJOR_VERSION 3
|
||||
#define EEPP_MINOR_VERSION 1
|
||||
#define EEPP_MAJOR_VERSION 4
|
||||
#define EEPP_MINOR_VERSION 0
|
||||
#define EEPP_PATCH_LEVEL 0
|
||||
#define EEPP_CODENAME "Khaya"
|
||||
#define EEPP_CODENAME "Asādhāraṇa"
|
||||
|
||||
/** The compiled version of the library */
|
||||
#define EEPP_VERSION( x ) \
|
||||
|
||||
@@ -25,8 +25,11 @@ enum WindowStyle {
|
||||
Resize = ( 1 << 2 ),
|
||||
Fullscreen = ( 1 << 3 ),
|
||||
UseDesktopResolution = ( 1 << 4 ),
|
||||
Hidden = ( 1 << 5 ),
|
||||
#if EE_PLATFORM == EE_PLATFORM_IOS || EE_PLATFORM == EE_PLATFORM_ANDROID
|
||||
Default = Borderless
|
||||
#elif defined( EE_UNIT_TESTS )
|
||||
Default = Titlebar | Resize | Hidden
|
||||
#else
|
||||
Default = Titlebar | Resize
|
||||
#endif
|
||||
|
||||
@@ -1954,6 +1954,7 @@ solution "eepp"
|
||||
project "eepp-unit_tests"
|
||||
kind "ConsoleApp"
|
||||
targetdir("./bin/unit_tests")
|
||||
defines { "EE_UNIT_TESTS" }
|
||||
links { "eterm-static", "languages-syntax-highlighting-static" }
|
||||
includedirs { "src/modules/eterm/include/", "src/thirdparty" }
|
||||
language "C++"
|
||||
|
||||
@@ -1982,6 +1982,7 @@ workspace "eepp"
|
||||
project "eepp-unit_tests"
|
||||
kind "ConsoleApp"
|
||||
targetdir(_MAIN_SCRIPT_DIR .. "/bin/unit_tests")
|
||||
defines { "EE_UNIT_TESTS" }
|
||||
links { "eterm-static", "languages-syntax-highlighting-static" }
|
||||
incdirs { "src/modules/eterm/include/", "src/thirdparty" }
|
||||
language "C++"
|
||||
|
||||
@@ -84,6 +84,13 @@ bool WindowSDL::create( WindowSettings Settings, ContextSettings Context ) {
|
||||
mWindow.WindowConfig = Settings;
|
||||
mWindow.ContextConfig = Context;
|
||||
|
||||
#if defined( EE_X11_PLATFORM )
|
||||
// Unmapped GLX windows do not provide reliable front-buffer storage. Keep hidden windows
|
||||
// double-buffered so rendering and readback use the drawable's back buffer.
|
||||
if ( mWindow.WindowConfig.Style & WindowStyle::Hidden )
|
||||
mWindow.ContextConfig.DoubleBuffering = true;
|
||||
#endif
|
||||
|
||||
if ( !SDL_WasInit( SDL_INIT_VIDEO ) && SDL_Init( SDL_INIT_VIDEO ) != 0 ) {
|
||||
Log::error( "Unable to initialize SDL: %s", SDL_GetError() );
|
||||
|
||||
@@ -106,7 +113,9 @@ bool WindowSDL::create( WindowSettings Settings, ContextSettings Context ) {
|
||||
mWindow.WindowConfig.Height = mWindow.DesktopResolution.getHeight();
|
||||
}
|
||||
|
||||
mWindow.Flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN |
|
||||
mWindow.Flags = SDL_WINDOW_OPENGL |
|
||||
( ( mWindow.WindowConfig.Style & WindowStyle::Hidden ) ? SDL_WINDOW_HIDDEN
|
||||
: SDL_WINDOW_SHOWN ) |
|
||||
( ( !mWindow.WindowConfig.DisableHiDPI ? SDL_WINDOW_ALLOW_HIGHDPI : 0 ) );
|
||||
|
||||
if ( mWindow.WindowConfig.Style & WindowStyle::Resize ) {
|
||||
@@ -284,6 +293,9 @@ bool WindowSDL::create( WindowSettings Settings, ContextSettings Context ) {
|
||||
Backend::BackendHelper::setUserTheme( (HWND)getWindowHandler() );
|
||||
#endif
|
||||
|
||||
if ( mWindow.WindowConfig.Style & WindowStyle::Hidden )
|
||||
SDL_HideWindow( mSDLWindow );
|
||||
|
||||
logSuccessfulInit( getVersion() );
|
||||
|
||||
return true;
|
||||
|
||||
@@ -69,6 +69,13 @@ bool WindowSDL::create( WindowSettings Settings, ContextSettings Context ) {
|
||||
mWindow.WindowConfig = Settings;
|
||||
mWindow.ContextConfig = Context;
|
||||
|
||||
#if defined( EE_X11_PLATFORM )
|
||||
// Unmapped GLX windows do not provide reliable front-buffer storage. Keep hidden windows
|
||||
// double-buffered so rendering and readback use the drawable's back buffer.
|
||||
if ( mWindow.WindowConfig.Style & WindowStyle::Hidden )
|
||||
mWindow.ContextConfig.DoubleBuffering = true;
|
||||
#endif
|
||||
|
||||
if ( !SDL_WasInit( SDL_INIT_VIDEO ) && !SDL_Init( SDL_INIT_VIDEO ) ) {
|
||||
Log::error( "Unable to initialize SDL: %s", SDL_GetError() );
|
||||
|
||||
@@ -96,8 +103,10 @@ bool WindowSDL::create( WindowSettings Settings, ContextSettings Context ) {
|
||||
mWindow.WindowConfig.Height = mWindow.DesktopResolution.getHeight();
|
||||
}
|
||||
|
||||
mWindow.Flags = SDL_WINDOW_OPENGL |
|
||||
( ( !mWindow.WindowConfig.DisableHiDPI ? SDL_WINDOW_HIGH_PIXEL_DENSITY : 0 ) );
|
||||
mWindow.Flags =
|
||||
SDL_WINDOW_OPENGL |
|
||||
( ( mWindow.WindowConfig.Style & WindowStyle::Hidden ) ? SDL_WINDOW_HIDDEN : 0 ) |
|
||||
( ( !mWindow.WindowConfig.DisableHiDPI ? SDL_WINDOW_HIGH_PIXEL_DENSITY : 0 ) );
|
||||
|
||||
if ( mWindow.WindowConfig.Style & WindowStyle::Resize ) {
|
||||
mWindow.Flags |= SDL_WINDOW_RESIZABLE;
|
||||
@@ -259,6 +268,9 @@ bool WindowSDL::create( WindowSettings Settings, ContextSettings Context ) {
|
||||
Backend::BackendHelper::setUserTheme( (HWND)getWindowHandler() );
|
||||
#endif
|
||||
|
||||
if ( mWindow.WindowConfig.Style & WindowStyle::Hidden )
|
||||
SDL_HideWindow( mSDLWindow );
|
||||
|
||||
logSuccessfulInit( getVersion() );
|
||||
|
||||
return true;
|
||||
|
||||
@@ -14,7 +14,7 @@ using namespace EE::System;
|
||||
using namespace EE::Graphics;
|
||||
using namespace EE::Window;
|
||||
|
||||
static constexpr Uint32 VisualTestWindowStyle = WindowStyle::Borderless;
|
||||
static constexpr Uint32 VisualTestWindowStyle = WindowStyle::Borderless | WindowStyle::Hidden;
|
||||
|
||||
static void compareImages( utest_state_s& utest_state, int* utest_result, EE::Window::Window* win,
|
||||
const std::string& imageName,
|
||||
|
||||
@@ -8,7 +8,7 @@ using namespace EE;
|
||||
|
||||
#define ECODE_MAJOR_VERSION 0
|
||||
#define ECODE_MINOR_VERSION 8
|
||||
#define ECODE_PATCH_LEVEL 1
|
||||
#define ECODE_PATCH_LEVEL 2
|
||||
/* ECODE_COMMIT_NUMBER 9999 is used for official releases, nightly builds (pre-releases) will
|
||||
* contain the number of commits after the last official release
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user