This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch wl/tests-module
in repository enlightenment.
View the commit online.
commit b5e6c906caad7b71ee84af5806de6a628780b4d3
Author: Cedric BAIL <[email protected]>
AuthorDate: Fri Aug 7 23:14:05 2026 -0600
tests - add a -Dtests option, the check harness and a wltest profile
Groundwork for an automated Wayland test suite. E has no test runner at
all today: src/tests/ holds eight standalone X11 clients that are driven
by hand and are not in the build.
Three pieces, none of them wired to a test yet:
- a 'tests' meson option, default false, gating a new src/tests build;
- efl_check.h and timeout.c, copied verbatim from core/efl src/tests/.
EFL already has a check(1) harness with EFL_START_TEST/EFL_END_TEST,
fork-mode isolation and meson test() wiring. Same project, same
idioms - better to reuse it than invent a second one. Prefer
re-syncing from EFL over editing these locally;
- a 'wltest' config profile, installed only with -Dtests=true.
The profile needs a word of explanation. The default profile enables
exactly one module, wizard, and expects the wizard to set up everything
else on first run. That is wrong twice over for a test: the wizard opens
a window and waits for input, and wl_desktop_shell is never loaded, so
xdg_wm_base is not advertised and there is almost nothing left to test.
wltest is the default profile with that one module swapped.
Keep the module list there minimal and explicit. A test that needs
another module should say so, rather than the suite quietly depending on
whatever the default profile happens to enable this release.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01FtoiXoSKUmZb6Aix6U3GZS
---
data/config/meson.build | 6 +
data/config/wltest/e.src | 248 +++++++++++++++++++
data/config/wltest/e_bindings.src | 257 +++++++++++++++++++
data/config/wltest/meson.build | 19 ++
meson_options.txt | 4 +
src/tests/efl_check.h | 506 ++++++++++++++++++++++++++++++++++++++
src/tests/meson.build | 11 +
src/tests/timeout.c | 17 ++
8 files changed, 1068 insertions(+)
diff --git a/data/config/meson.build b/data/config/meson.build
index a63ded7ef..10c1868b0 100644
--- a/data/config/meson.build
+++ b/data/config/meson.build
@@ -18,3 +18,9 @@ custom_target('profile.src',
subdir('default')
subdir('standard')
subdir('tiling')
+
+# Profile used by the Wayland test suite; only worth installing when the
+# tests are built.
+if get_option('tests') == true
+ subdir('wltest')
+endif
diff --git a/data/config/wltest/e.src b/data/config/wltest/e.src
new file mode 100644
index 000000000..6d5c12433
--- /dev/null
+++ b/data/config/wltest/e.src
@@ -0,0 +1,248 @@
+// Profile used by the Wayland test suite (E_CONF_PROFILE=wltest).
+//
+// A copy of the "default" profile with exactly one change: the module list
+// loads wl_desktop_shell instead of wizard. The wizard would otherwise open a
+// window and wait for input on every test run, and the default profile does
+// not load wl_desktop_shell at all -- so without this, xdg_wm_base is never
+// advertised and almost nothing is testable.
+//
+// Keep this list minimal and explicit. A test that needs another module
+// should say so, rather than the suite quietly depending on whatever the
+// default profile happens to enable this release.
+group "E_Config" struct {
+ value "config_version" int: 1000035;
+ value "config_type" uint: 0; // this profile seems to just be super minimalist
+ value "desktop_default_name" string: "%i-%i";
+ value "desktop_default_window_profile" string: "";
+ value "menus_scroll_speed" double: 1000.0;
+ value "menus_fast_mouse_move_threshhold" double: 300.0;
+ value "menus_click_drag_timeout" double: 0.25;
+ value "border_shade_animate" int: 1;
+ value "border_shade_transition" int: 3;
+ value "border_shade_speed" double: 3000.0;
+ value "priority" int: 3;
+ value "image_cache" int: 4096;
+ value "font_cache" int: 512;
+ value "edje_cache" int: 10;
+ value "edje_collection_cache" int: 30;
+ value "zone_desks_x_count" int: 1;
+ value "zone_desks_y_count" int: 1;
+ value "show_desktop_icons" int: 1;
+ value "edge_flip_dragging" int: 0;
+ value "use_shaped_win" int: 0;
+ group "modules" list {
+ group "E_Config_Module" struct {
+ value "name" string: "wl_desktop_shell";
+ value "enabled" uchar: 1;
+ }
+ }
+ value "window_placement_policy" int: 0;
+ value "window_grouping" int: 0;
+ value "focus_policy" int: 0;
+ value "focus_setting" int: 1;
+ value "pass_click_on" int: 1;
+ value "always_click_to_raise" int: 0;
+ value "always_click_to_focus" int: 0;
+ value "use_auto_raise" int: 0;
+ value "auto_raise_delay" double: 0.5;
+ value "use_resist" int: 1;
+ value "drag_resist" int: 16;
+ value "desk_resist" int: 32;
+ value "window_resist" int: 12;
+ value "gadget_resist" int: 32;
+ value "geometry_auto_resize_limit" int: 1;
+ value "geometry_auto_move" int: 1;
+ value "winlist_warp_while_selecting" int: 0;
+ value "winlist_warp_at_end" int: 1;
+ value "pointer_warp_speed" double: 0.1;
+ value "winlist_scroll_animate" int: 1;
+ value "winlist_scroll_speed" double: 0.1;
+ value "winlist_list_show_iconified" int: 1;
+ value "winlist_list_show_other_desk_iconified" int: 1;
+ value "winlist_list_show_other_screen_iconified" int: 0;
+ value "winlist_list_show_other_desk_windows" int: 0;
+ value "winlist_list_show_other_screen_windows" int: 0;
+ value "winlist_list_uncover_while_selecting" int: 0;
+ value "winlist_list_jump_desk_while_selecting" int: 0;
+ value "winlist_list_focus_while_selecting" int: 0;
+ value "winlist_list_raise_while_selecting" int: 0;
+ value "winlist_mode" int: 1;
+ value "winlist_large_size" double: 0.6666;
+ value "winlist_list_size" double: 0.3333;
+ value "winlist_list_no_miniatures" uchar: 0;
+ value "no_state_hidden_desktop" uchar: 0;
+ value "maximize_policy" int: 49;
+ value "allow_manip" int: 0;
+ value "border_fix_on_shelf_toggle" int: 0;
+ value "allow_above_fullscreen" int: 0;
+ value "kill_if_close_not_possible" int: 1;
+ value "kill_process" int: 1;
+ value "kill_timer_wait" double: 10.0;
+ value "ping_clients" int: 1;
+ value "transition_desk" string: "vswipe";
+ value "transition_change" string: "crossfade";
+ value "remember_internal_windows" int: 0;
+ value "move_info_follows" int: 1;
+ value "resize_info_follows" int: 1;
+ value "move_info_visible" int: 1;
+ value "resize_info_visible" int: 1;
+ value "focus_last_focused_per_desktop" int: 1;
+ value "focus_revert_on_hide_or_close" int: 1;
+ value "pointer_slide" int: 0;
+ value "use_e_cursor" int: 1;
+ value "cursor_size" int: 32;
+ value "menu_autoscroll_margin" int: 0;
+ value "menu_autoscroll_cursor_margin" int: 1;
+ value "transient.move" int: 1;
+ value "transient.resize" int: 0;
+ value "transient.raise" int: 1;
+ value "transient.lower" int: 1;
+ value "transient.layer" int: 1;
+ value "transient.desktop" int: 1;
+ value "transient.iconify" int: 1;
+ value "modal_windows" int: 1;
+ value "menu_eap_name_show" int: 1;
+ value "menu_eap_generic_show" int: 1;
+ value "menu_eap_comment_show" int: 0;
+ value "menu_gadcon_client_toplevel" int: 0;
+ value "fullscreen_policy" int: 0;
+ value "exebuf_term_cmd" string: "xterm -hold -e";
+ value "use_app_icon" int: 0;
+ value "cnfmdlg_disabled" int: 0;
+ value "cfgdlg_auto_apply" int: 0;
+ value "cfgdlg_default_mode" int: 0;
+ value "font_hinting" int: 0;
+ value "desklock_background" string: "theme_desklock_background";
+ value "desklock_auth_method" int: 0;
+ value "desklock_login_box_zone" int: -1;
+ value "desklock_start_locked" int: 0;
+ value "desklock_on_suspend" int: 0;
+ value "desklock_autolock_screensaver" int: 0;
+ value "desklock_post_screensaver_time" double: 0.0;
+ value "desklock_use_custom_desklock" int: 0;
+ value "desklock_ask_presentation" uchar: 1;
+ value "desklock_ask_presentation_timeout" double: 30;
+ value "display_res_restore" int: 0;
+ value "display_res_width" int: 1;
+ value "display_res_height" int: 1;
+ value "display_res_hz" int: 0;
+ value "display_res_rotation" int: 0;
+ value "screensaver_enable" int: 0;
+ value "screensaver_timeout" int: 60;
+ value "screensaver_interval" int: 5;
+ value "screensaver_blanking" int: 2;
+ value "screensaver_expose" int: 2;
+ value "screensaver_ask_presentation" uchar: 1;
+ value "screensaver_ask_presentation_timeout" double: 30;
+ value "dpms_enable" int: 1;
+ value "dpms_standby_enable" int: 1;
+ value "dpms_suspend_enable" int: 1;
+ value "dpms_off_enable" int: 1;
+ value "dpms_standby_timeout" int: 300;
+ value "dpms_suspend_timeout" int: 300;
+ value "dpms_off_timeout" int: 300;
+ value "clientlist_group_by" int: 0;
+ value "clientlist_include_all_zones" int: 0;
+ value "clientlist_separate_with" int: 0;
+ value "clientlist_sort_by" int: 0;
+ value "clientlist_separate_iconified_apps" int: 0;
+ value "clientlist_warp_to_iconified_desktop" int: 0;
+ value "clientlist_limit_caption_len" int: 0;
+ value "clientlist_max_caption_len" int: 2;
+ value "mouse_hand" int: 1;
+ value "mouse_accel" double: 0.0;
+ value "mouse_flat_accel" uchar: 0;
+ value "mouse_hires_scroll" uchar: 1;
+ value "mouse_accel_threshold" int: 4;
+ value "mouse_natural_scroll" uchar: 0;
+ value "mouse_emulate_middle_button" uchar: 1;
+ value "touch_accel" double: 0.0;
+ value "touch_natural_scroll" uchar: 0;
+ value "touch_emulate_middle_button" uchar: 1;
+ value "touch_tap_to_click" uchar: 0;
+ value "touch_flat_accel" uchar: 0;
+ value "touch_clickpad" uchar: 1;
+ value "touch_scrolling_2finger" uchar: 1;
+ value "touch_scrolling_edge" uchar: 0;
+ value "touch_scrolling_circular" uchar: 0;
+ value "touch_scrolling_horiz" uchar: 1;
+ value "touch_palm_detect" uchar: 1;
+ value "border_raise_on_mouse_action" int: 1;
+ value "desk_flip_wrap" int: 0;
+ value "fullscreen_flip" int: 1;
+ value "icon_theme" string: "hicolor";
+ value "desk_flip_animate_mode" int: 0;
+ value "desk_flip_animate_interpolation" int: 0;
+ value "desk_flip_animate_time" double: 0.5;
+ value "wallpaper_import_last_dev" string: "/tmp";
+ value "wallpaper_import_last_path" string: "/";
+ value "theme_default_border_style" string: "default";
+ value "desk_auto_switch" int: 0;
+ value "thumb_nice" int: 0;
+ value "gesture_open_input_devices" int: 0;
+ value "screen_limits" int: 0;
+ value "menu_favorites_show" int: 1;
+ value "menu_apps_show" int: 1;
+ value "ping_clients_interval" int: 16;
+ value "cache_flush_poll_interval" int: 528;
+ value "thumbscroll_enable" int: 1;
+ value "thumbscroll_threshhold" int: 24;
+ value "thumbscroll_momentum_threshhold" double: 0.0;
+ value "thumbscroll_friction" double: 1.0;
+ value "dbus_desktop" int: 1;
+ value "border_keyboard.timeout" double: 5.0;
+ value "border_keyboard.move.dx" uchar: 5;
+ value "border_keyboard.move.dy" uchar: 5;
+ value "border_keyboard.resize.dx" uchar: 5;
+ value "border_keyboard.resize.dy" uchar: 5;
+ value "dbus_desktop" int: 1;
+ value "scale.min" double: 0.8;
+ value "scale.max" double: 5.0;
+ value "scale.factor" double: 1.0;
+ value "scale.base_dpi" int: 90;
+ value "scale.use_dpi" uchar: 1;
+ value "scale.use_custom" uchar: 0;
+ value "scale.xapp_base_dpi" int: 75;
+ value "scale.set_xapp_dpi" uchar: 1;
+ value "show_cursor" uchar: 1;
+ value "idle_cursor" uchar: 1;
+ value "default_system_menu" string: "";
+ value "cfgdlg_normal_wins" uchar: 0;
+ value "syscon.main.icon_size" int: 64;
+ value "syscon.secondary.icon_size" int: 48;
+ value "syscon.extra.icon_size" int: 48;
+ value "syscon.timeout" double: 0.0;
+ value "syscon.do_input" uchar: 0;
+ value "exec.expire_timeout" double: 30.0;
+ value "exec.show_run_dialog" uchar: 1;
+ value "exec.show_exit_dialog" uchar: 1;
+ value "null_container_win" uchar: 1;
+ value "backlight.normal" double: 1.0;
+ value "backlight.dim" double: 0.3;
+ value "backlight.transition" double: 0.5;
+ value "backlight.timer" double: 30.0;
+ value "backlight.battery_timer" double: 20.0;
+ value "backlight.idle_dim" uchar: 1;
+ value "backlight.ddc" uchar: 0;
+ value "device_desktop" int: 0;
+ value "device_auto_mount" int: 0;
+ value "device_auto_open" int: 0;
+ value "xsettings.match_e17_theme" uchar: 1;
+ value "xsettings.match_e17_icon_theme" uchar: 1;
+ value "update.check" uchar: 0;
+ value "update.later" uchar: 0;
+ value "xkb.only_label" int: 0;
+ value "xkb.default_model" string: "default";
+ value "xkb.use_cache" uchar: 0;
+ value "keyboard.repeat_delay" int: 400;
+ value "keyboard.repeat_rate" int: 25;
+ value "exe_always_single_instance" uchar: 0;
+ value "use_desktop_window_profile" int: 0;
+ value "powersave.none" double: 0.25;
+ value "powersave.low" double: 5.0;
+ value "powersave.medium" double: 60.0;
+ value "powersave.high" double: 300.0;
+ value "powersave.extreme" double: 1200.0;
+ value "powersave.min" int: 0;
+ value "powersave.max" int: 5;
+}
diff --git a/data/config/wltest/e_bindings.src b/data/config/wltest/e_bindings.src
new file mode 100644
index 000000000..0f11f7e11
--- /dev/null
+++ b/data/config/wltest/e_bindings.src
@@ -0,0 +1,257 @@
+group "E_Config_Bindings" struct {
+ value "config_version" int: 0;
+ group "mouse_bindings" list {
+ group "E_Config_Binding_Mouse" struct {
+ value "context" int: 3;
+ value "modifiers" int: 0;
+ value "action" string: "menu_show";
+ value "params" string: "main";
+ value "button" uchar: 1;
+ value "any_mod" uchar: 0;
+ }
+ }
+ group "signal_bindings" list {
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,down,1,double";
+ value "source" string: "e.event.titlebar";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_shaded_toggle";
+ value "params" string: "up";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,down,2";
+ value "source" string: "e.event.titlebar";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_shaded_toggle";
+ value "params" string: "up";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,wheel,?,1";
+ value "source" string: "e.event.titlebar";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_shaded";
+ value "params" string: "0 up";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,wheel,?,-1";
+ value "source" string: "e.event.titlebar";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_shaded";
+ value "params" string: "1 up";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,clicked,3";
+ value "source" string: "e.event.titlebar";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_menu";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,clicked,?";
+ value "source" string: "e.event.icon";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_menu";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,clicked,[12]";
+ value "source" string: "e.event.close";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_close";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,clicked,3";
+ value "source" string: "e.event.close";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_kill";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,clicked,1";
+ value "source" string: "e.event.maximize";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_maximized_toggle";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,clicked,2";
+ value "source" string: "e.event.maximize";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_maximized_toggle";
+ value "params" string: "smart";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,clicked,3";
+ value "source" string: "e.event.maximize";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_maximized_toggle";
+ value "params" string: "expand";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,clicked,?";
+ value "source" string: "e.event.minimize";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_iconic_toggle";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,clicked,?";
+ value "source" string: "e.event.shade";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_shaded_toggle";
+ value "params" string: "up";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,clicked,?";
+ value "source" string: "e.event.lower";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_lower";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,down,1";
+ value "source" string: "e.event.icon";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_drag_icon";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,down,1";
+ value "source" string: "e.event.titlebar";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_move";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,up,1";
+ value "source" string: "e.event.titlebar";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_move";
+ value "params" string: "end";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,down,1";
+ value "source" string: "e.event.resize.tl";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_resize";
+ value "params" string: "tl";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,down,1";
+ value "source" string: "e.event.resize.t";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_resize";
+ value "params" string: "t";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,down,1";
+ value "source" string: "e.event.resize.tr";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_resize";
+ value "params" string: "tr";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,down,1";
+ value "source" string: "e.event.resize.r";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_resize";
+ value "params" string: "r";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,down,1";
+ value "source" string: "e.event.resize.br";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_resize";
+ value "params" string: "br";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,down,1";
+ value "source" string: "e.event.resize.b";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_resize";
+ value "params" string: "b";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,down,1";
+ value "source" string: "e.event.resize.bl";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_resize";
+ value "params" string: "bl";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,down,1";
+ value "source" string: "e.event.resize.l";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_resize";
+ value "params" string: "l";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,up,1";
+ value "source" string: "e.event.resize.*";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_resize";
+ value "params" string: "end";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,down,3";
+ value "source" string: "e.event.resize.*";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_move";
+ }
+ group "E_Config_Binding_Signal" struct {
+ value "context" int: 2;
+ value "signal" string: "mouse,up,3";
+ value "source" string: "e.event.resize.*";
+ value "modifiers" int: 0;
+ value "any_mod" uchar: 1;
+ value "action" string: "window_move";
+ value "params" string: "end";
+ }
+ }
+}
diff --git a/data/config/wltest/meson.build b/data/config/wltest/meson.build
new file mode 100644
index 000000000..ce49a7e84
--- /dev/null
+++ b/data/config/wltest/meson.build
@@ -0,0 +1,19 @@
+dir = 'wltest'
+src = [
+ 'e',
+ 'e_bindings'
+]
+
+##### boilerplate config build + install of icons/dirs
+i = 0
+foreach cd: src
+ custom_target(' '.join(['config_dist', dir, cd]),
+ input : cd + '.src',
+ output : cd + '.cfg',
+ command : [eet_cmd, '-e', '@OUTPUT@', 'config', '@INPUT@', '1'],
+ install : true,
+ install_dir : join_paths(dir_config, dir),
+ install_mode : 'rw-r--r--'
+ )
+ i += 1
+endforeach
diff --git a/meson_options.txt b/meson_options.txt
index 70b30bb30..6e81f6551 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -330,3 +330,7 @@ option('clipboard',
type: 'boolean',
value: true,
description: 'enable clipboard module: (default=true)')
+option('tests',
+ type: 'boolean',
+ value: false,
+ description: 'build the test suites: (default=false)')
diff --git a/src/tests/efl_check.h b/src/tests/efl_check.h
new file mode 100644
index 000000000..ef2c68399
--- /dev/null
+++ b/src/tests/efl_check.h
@@ -0,0 +1,506 @@
+/* Test harness macros and check(1) suite runner.
+ *
+ * Copied verbatim from core/efl src/tests/efl_check.h so that E's Wayland
+ * test suite uses the same idioms as EFL's. Keep changes here to a minimum
+ * and prefer re-syncing from EFL over local edits.
+ */
+#ifndef EFL_CHECK_H
+#define EFL_CHECK_H
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h> /* getenv */
+#include <stdio.h> /* fprintf, fputs */
+#include <string.h> /* strcmp */
+#include <unistd.h> /* execvp */
+#include <errno.h> /* errno */
+#include <sys/time.h>
+
+#ifdef HAVE_FORK
+# ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+# endif
+# ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+# endif
+# include <signal.h>
+#endif
+
+#include <Eina.h>
+
+#ifndef EINA_UNUSED
+
+# ifdef __GNUC__
+
+# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+# define EINA_UNUSED __attribute__ ((__unused__))
+# else
+# define EINA_UNUSED
+# endif
+# else
+# define EINA_UNUSED
+# endif
+
+#endif
+
+#ifdef HAVE_GETTIMEOFDAY
+# if CHECK_MINOR_VERSION >= 11
+# define ENABLE_TIMING_INFO
+# endif
+#endif
+
+/* Uncomment this line to print a warning line to stdout for every expected error received.
+ Otherwise, expected errors are just silently ignored, greatly reducing the log size.
+*/
+//#define PRINT_EXPECTED_ERROR
+
+#define DISABLE_ABORT_ON_CRITICAL_START \
+ do { \
+ int ___val = eina_log_abort_on_critical_get(); \
+ eina_log_abort_on_critical_set(0)
+
+#define DISABLE_ABORT_ON_CRITICAL_END \
+ eina_log_abort_on_critical_set(___val); \
+ } while (0)
+
+#define EXPECT_ERROR_START \
+ do { \
+ DISABLE_ABORT_ON_CRITICAL_START; \
+ Eina_Bool expect_error_start = EINA_FALSE; \
+ do { \
+ eina_log_print_cb_set(_efl_test_expect_error, &expect_error_start); \
+ } while(0)
+
+
+#define EXPECT_ERROR_END \
+ eina_log_print_cb_set(NULL, NULL); \
+ ck_assert_int_eq(expect_error_start, EINA_TRUE); \
+ DISABLE_ABORT_ON_CRITICAL_END; \
+ } while(0)
+
+typedef struct _Efl_Test_Case Efl_Test_Case;
+struct _Efl_Test_Case
+{
+ const char *test_case;
+ void (*build)(TCase *tc);
+};
+
+#ifdef HAVE_FORK
+static int timeout_pid = 0;
+#endif
+
+EINA_UNUSED static void
+_efl_test_expect_error(const Eina_Log_Domain *d EINA_UNUSED, Eina_Log_Level level, const char *file EINA_UNUSED, const char *fnc, int line EINA_UNUSED, const char *fmt EINA_UNUSED, void *data, va_list args EINA_UNUSED)
+{
+ Eina_Bool *error = (Eina_Bool*) data;
+ if (level == EINA_LOG_LEVEL_ERR) *error = EINA_TRUE;
+#ifdef PRINT_EXPECTED_ERROR
+ printf("EXPECTED ERROR %s\n", fnc);
+#else
+ (void)fnc;
+#endif
+}
+
+static void
+_efl_tests_list(const Efl_Test_Case *etc)
+{
+ const Efl_Test_Case *itr = etc;
+ fputs("Available Test Cases:\n", stderr);
+ for (; itr->test_case; itr++)
+ fprintf(stderr, "\t%s\n", itr->test_case);
+}
+
+EINA_UNUSED static int
+_efl_test_option_disp(int argc, char **argv, const Efl_Test_Case *etc)
+{
+ int i;
+
+ for (i = 1; i < argc; i++)
+ {
+ if ((strcmp(argv[i], "-h") == 0) ||
+ (strcmp(argv[i], "--help") == 0))
+ {
+ fprintf(stderr, "Usage: %s [options] [test_case1 .. [test_caseN]]\n",
+ argv[0]);
+ fprintf(stderr, " -l\t--list\t\tList all tests case.\n");
+ fprintf(stderr, " \t--valgrind\tRun the tests under valgrind.\n");
+ fprintf(stderr, "\nNote that CK_RUN_CASE=test_case does also filter which tests are run\n");
+ return 0;
+ }
+ else if ((strcmp(argv[i], "-l") == 0) ||
+ (strcmp(argv[i], "--list") == 0))
+ {
+ _efl_tests_list(etc);
+ return 0;
+ }
+ else if (strcmp(argv[i], "--valgrind") == 0)
+ {
+ const char ** nav = (const char **) alloca(sizeof(char*) * (argc + 3));
+ int j, k;
+
+ nav[0] = "valgrind";
+ nav[1] = "--trace-children=yes";
+ for (j = 0, k = 2; j < argc; j++)
+ {
+ if (i == j) continue ; // Remove --valgrind
+ nav[k++] = argv[j];
+ }
+
+ nav[k] = NULL;
+ execvp("valgrind", (char**) nav);
+ fprintf(stderr, "Failed to execute valgrind due to '%s'\n", strerror(errno));
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int
+_efl_test_use(int argc, const char **argv, const char *test_case)
+{
+ if (argc < 1)
+ return 1;
+
+ for (; argc > 0; argc--, argv++)
+ if (strcasecmp(test_case, *argv) == 0)
+ return 1;
+ return 0;
+}
+
+#ifdef HAVE_FORK
+static int
+_efl_test_fork_has(SRunner *sr)
+{
+ if (srunner_fork_status(sr) == CK_FORK)
+ return 1;
+ else if (srunner_fork_status(sr) == CK_NOFORK)
+ return 0;
+ else if (srunner_fork_status(sr) == CK_FORK_GETENV)
+ {
+ char *res;
+
+ res = getenv("CK_FORK");
+ if (res && (strcmp(res, "no") == 0))
+ return 0;
+ else
+ return 1;
+ }
+
+ /* should never get there */
+ return 0;
+}
+#endif
+
+#ifdef ENABLE_TIMING_INFO
+EINA_UNUSED static double _timing_start_time;
+
+static int
+_timing_enabled(void)
+{
+ const char *lc = getenv("TIMING_ENABLED");
+ return !!lc;
+}
+
+static double
+_timing_time_get(void)
+{
+ struct timeval timev;
+
+ gettimeofday(&timev, NULL);
+ return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
+}
+
+EINA_UNUSED static void
+_timing_start(void)
+{
+ if (_timing_enabled())
+ _timing_start_time = _timing_time_get();
+}
+
+EINA_UNUSED static void
+_timing_end(void)
+{
+ double diff;
+ static int thres_set = 0;
+ static double thres = 0;
+
+ if (!_timing_enabled()) return;
+ if (!thres_set)
+ {
+ const char *env = getenv("TIME_DIFF_THRESHOLD");
+
+ if (env)
+ {
+ thres = strtod(env, NULL);
+ if (thres > 0)
+ thres_set = 1;
+ }
+ if (!thres_set)
+ thres = 0.0001;
+ thres_set = 1;
+ }
+ diff = _timing_time_get() - _timing_start_time;
+
+ if (diff > thres)
+ printf("TIME %s: %.5g\n", tcase_name(), diff);
+}
+
+# define EFL_START_TEST(TEST_NAME) \
+ START_TEST(TEST_NAME) \
+ { \
+ _timing_start();
+
+# define EFL_END_TEST \
+ _timing_end(); \
+ } \
+ END_TEST
+
+#else
+# define EFL_START_TEST(TEST_NAME) START_TEST(TEST_NAME)
+# define EFL_END_TEST END_TEST
+
+#endif
+
+static char srunner_xml_buf[4096];
+
+static int
+_efl_suite_run_end(SRunner *sr, const char *name)
+{
+ int failed_count;
+
+ if (name)
+ {
+ char *n = strdup(name);
+ char *p;
+
+ for (p = n; p[0]; p++)
+ {
+ switch (p[0])
+ {
+ case ' ':
+ case '/':
+ case '\\':
+ case ';':
+ p[0] = '_';
+ break;
+ }
+ }
+ snprintf(srunner_xml_buf, sizeof(srunner_xml_buf), TESTS_BUILD_DIR "/check-results-%s.xml", n);
+ srunner_set_xml(sr, srunner_xml_buf);
+ free(n);
+ }
+ else
+ srunner_set_xml(sr, TESTS_BUILD_DIR "/check-results.xml");
+ srunner_run_all(sr, CK_ENV);
+ failed_count = srunner_ntests_failed(sr);
+ srunner_free(sr);
+ return failed_count;
+}
+
+#ifdef HAVE_FORK
+static EINA_UNUSED Eina_Hash *fork_map;
+
+EINA_UNUSED static int
+_efl_suite_wait_on_fork(int *num_forks, Eina_Bool *timeout)
+{
+ int status = 0, ret, pid;
+ pid = waitpid(0, &status, 0);
+ if (WIFEXITED(status))
+ ret = WEXITSTATUS(status);
+ else
+ ret = 1;
+ if ((timeout_pid > 0) && (pid == timeout_pid))
+ *timeout = EINA_TRUE;
+ else if (timeout_pid > 0)
+ {
+ eina_hash_del_by_key(fork_map, &pid);
+ (*num_forks)--;
+ }
+ return ret;
+}
+#endif
+
+EINA_UNUSED static int
+_efl_suite_build_and_run(int argc, const char **argv, const char *suite_name, const Efl_Test_Case *etc, SFun init, SFun shutdown)
+{
+ Suite *s;
+ SRunner *sr;
+ TCase *tc;
+ int i, failed_count = 0;
+#ifdef HAVE_FORK
+ int do_fork;
+ int num_forks = 0;
+ int can_fork = 0;
+ Eina_Bool timeout_reached = EINA_FALSE;
+# ifdef ENABLE_TIMING_INFO
+ double tcstart = 0.0;
+# endif
+#endif
+#ifdef ENABLE_TIMING_INFO
+ double tstart = 0.0;
+ int timing;
+#endif
+
+#ifdef ENABLE_TIMING_INFO
+ timing = _timing_enabled();
+ if (timing)
+ tstart = _timing_time_get();
+#endif
+
+#ifdef HAVE_FORK
+# ifdef ENABLE_TIMING_INFO
+ if (timing)
+ tcstart = tstart;
+# endif
+#endif
+
+ fflush(stdout);
+ s = suite_create(suite_name);
+ sr = srunner_create(s);
+#ifdef HAVE_FORK
+ do_fork = _efl_test_fork_has(sr);
+ if (do_fork)
+ can_fork = !!etc[1].test_case /* can't parallelize 1 test */;
+#endif
+
+ for (i = 0; etc[i].test_case; ++i)
+ {
+#ifdef HAVE_FORK
+ int pid = 0;
+#endif
+
+ if (!_efl_test_use(argc, argv, etc[i].test_case))
+ continue;
+#ifdef HAVE_FORK
+ if (do_fork && can_fork)
+ {
+ if (!timeout_pid)
+ {
+ timeout_pid = fork();
+ if (timeout_pid == 0)
+ {
+ int ret = execl(PACKAGE_BUILD_DIR "/src/tests/timeout",
+ PACKAGE_BUILD_DIR "/src/tests/timeout",
+ (char *)NULL);
+ if (ret != 0)
+ {
+ fprintf(stderr, "EXECL %s TO RUN TIMEOUT!!!\n", PACKAGE_BUILD_DIR "/src/tests/timeout");
+ perror("EXECL");
+ fflush(stderr);
+ abort();
+ }
+ }
+ else if (timeout_pid < 0)
+ {
+ fprintf(stderr, "FORK TO RUN TIMEOUT TOOL FAILED!!!\n");
+ perror("FORK");
+ fflush(stderr);
+ abort();
+ }
+ }
+ if (num_forks == eina_cpu_count())
+ failed_count += _efl_suite_wait_on_fork(&num_forks, &timeout_reached);
+ if (timeout_reached) break;
+ pid = fork();
+ if (pid > 0)
+ {
+ if (!fork_map) fork_map = eina_hash_int32_new(NULL);
+ eina_hash_add(fork_map, &pid, etc[i].test_case);
+ num_forks++;
+# ifdef ENABLE_TIMING_INFO
+ if (timing)
+ tcstart = _timing_time_get();
+# endif
+ continue;
+ }
+ else if (pid < 0)
+ {
+ fprintf(stderr, "FORK TO RUN TIMEOUT TOOL FAILED!!!\n");
+ perror("FORK");
+ fflush(stderr);
+ abort();
+ }
+ }
+#endif
+
+ tc = tcase_create(etc[i].test_case);
+ if (init || shutdown)
+ tcase_add_checked_fixture(tc, init, shutdown);
+
+#ifdef HAVE_FORK
+ if (do_fork)
+ tcase_set_timeout(tc, 0);
+#endif
+
+ etc[i].build(tc);
+ suite_add_tcase(s, tc);
+#ifdef HAVE_FORK
+ if (do_fork && (!pid) && can_fork)
+ {
+ failed_count = _efl_suite_run_end(sr, etc[i].test_case);
+ if (failed_count > 255)
+ failed_count = 255;
+# ifdef ENABLE_TIMING_INFO
+ if (timing)
+ printf("TC TIME %s: %.5g\n", etc[i].test_case, _timing_time_get() - tcstart);
+# endif
+ exit(failed_count);
+ }
+#endif
+ }
+
+#ifdef HAVE_FORK
+ if (num_forks && (!timeout_reached))
+ {
+ do
+ {
+ failed_count += _efl_suite_wait_on_fork(&num_forks, &timeout_reached);
+ } while (num_forks && (!timeout_reached));
+ if (timeout_reached)
+ {
+ Eina_Iterator *it;
+ const char *testname;
+ it = eina_hash_iterator_data_new(fork_map);
+ timeout_pid = 0;
+ printf("FAILSAFE TIMEOUT REACHED!\n");
+ fflush(stdout);
+ EINA_ITERATOR_FOREACH(it, testname)
+ printf("STILL RUNNING: %s\n", testname);
+ fflush(stdout);
+ eina_iterator_free(it);
+ failed_count++;
+ }
+ }
+ else
+#endif
+ failed_count = _efl_suite_run_end(sr, NULL);
+
+#ifdef HAVE_FORK
+ if (timeout_pid)
+ {
+ kill(timeout_pid, SIGKILL);
+ timeout_pid = 0;
+ }
+ eina_hash_free(fork_map);
+ fork_map = NULL;
+#endif
+
+#ifdef ENABLE_TIMING_INFO
+ if (timing)
+ {
+ printf("SUITE TIME(%u) %s: %.5g\n", getpid(), suite_name, _timing_time_get() - tstart);
+ fflush(stdout);
+ }
+#endif
+ return failed_count;
+}
+
+#define SUITE_INIT(NAME) static void _##NAME##_suite_init(void)
+#define SUITE_INIT_FN(NAME) _##NAME##_suite_init
+#define SUITE_SHUTDOWN(NAME) static void _##NAME##_suite_shutdown(void)
+#define SUITE_SHUTDOWN_FN(NAME) _##NAME##_suite_shutdown
+
+#endif
diff --git a/src/tests/meson.build b/src/tests/meson.build
new file mode 100644
index 000000000..0f2a9ce30
--- /dev/null
+++ b/src/tests/meson.build
@@ -0,0 +1,11 @@
+# Test suites, built only with -Dtests=true.
+#
+# The .c files sitting directly in this directory are older standalone X11
+# clients driven by hand; they are deliberately left out of the build.
+
+# Watchdog helper forked by efl_check.h when running suites in fork mode.
+executable('timeout', 'timeout.c')
+
+if get_option('wl') == true
+ subdir('wayland')
+endif
diff --git a/src/tests/timeout.c b/src/tests/timeout.c
new file mode 100644
index 000000000..c3433970d
--- /dev/null
+++ b/src/tests/timeout.c
@@ -0,0 +1,17 @@
+/* Watchdog helper for efl_check.h's fork mode. Copied from core/efl
+ * src/tests/timeout.c. */
+#include <unistd.h>
+
+#if defined(__clang__)
+# pragma clang diagnostic ignored "-Wunused-parameter"
+#elif (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4
+# pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+
+int
+main(int arc, char *argv[])
+{
+ sleep(240);
+ return 0;
+}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.