This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch fix-modern-macos
in repository efl.
View the commit online.
commit 3be93e236c458133eb2d7eb846d4a0a6a3815f81
Author: Cedric BAIL <[email protected]>
AuthorDate: Wed Apr 29 17:51:30 2026 -0600
test(elementary): add unit tests for elm_open_url/_file/_email
Uses a mocked-helper trick: prepends a temp directory to PATH containing
a stub script named 'open' (macOS) or 'xdg-open' / 'xdg-email' (Linux)
that records its argv to a temp file. The test then verifies the right
binary was invoked with the right argument.
---
src/tests/elementary/elm_suite.c | 1 +
src/tests/elementary/elm_suite.h | 1 +
src/tests/elementary/elm_test_open.c | 214 +++++++++++++++++++++++++++++++++++
src/tests/elementary/meson.build | 1 +
4 files changed, 217 insertions(+)
diff --git a/src/tests/elementary/elm_suite.c b/src/tests/elementary/elm_suite.c
index a2d38c4c77..8071712177 100644
--- a/src/tests/elementary/elm_suite.c
+++ b/src/tests/elementary/elm_suite.c
@@ -60,6 +60,7 @@ static const Efl_Test_Case etc[] = {
{ "elm_hoversel", elm_test_hoversel},
{ "elm_multibuttonentry", elm_test_multibuttonentry},
{ "elm_naviframe", elm_test_naviframe},
+ { "elm_open", elm_test_open },
{ "elm_popup", elm_test_popup},
{ "elm_bubble", elm_test_bubble},
{ "elm_clock", elm_test_clock},
diff --git a/src/tests/elementary/elm_suite.h b/src/tests/elementary/elm_suite.h
index 5fbd8fa742..d9923ab2ea 100644
--- a/src/tests/elementary/elm_suite.h
+++ b/src/tests/elementary/elm_suite.h
@@ -70,6 +70,7 @@ void elm_test_fileselector_entry(TCase *tc);
void elm_test_hoversel(TCase *tc);
void elm_test_multibuttonentry(TCase *tc);
void elm_test_naviframe(TCase *tc);
+void elm_test_open(TCase *tc);
void elm_test_popup(TCase *tc);
void elm_test_bubble(TCase *tc);
void elm_test_clock(TCase *tc);
diff --git a/src/tests/elementary/elm_test_open.c b/src/tests/elementary/elm_test_open.c
new file mode 100644
index 0000000000..d1c1440d1b
--- /dev/null
+++ b/src/tests/elementary/elm_test_open.c
@@ -0,0 +1,214 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#include <Elementary.h>
+#include "elm_suite.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* Build a temp dir, drop a stub script in it that records its argv to a
+ * known temp file, and prepend the dir to PATH. ecore_exe_run will then
+ * pick up the stub instead of the real xdg-open / open. */
+
+static char _stub_dir[256];
+static char _record_path[256];
+static char _saved_path[4096];
+static char _current_stub_cmd[64] = {0};
+
+static void
+_install_stub(const char *cmd_name)
+{
+ char script_path[512];
+ FILE *f;
+ const char *cur;
+ char new_path[8192];
+
+ /* Record for the auto-teardown fixture */
+ snprintf(_current_stub_cmd, sizeof(_current_stub_cmd), "%s", cmd_name);
+
+ snprintf(_stub_dir, sizeof(_stub_dir), "/tmp/elm_open_test_XXXXXX");
+ /* mkdtemp modifies in place */
+ if (!mkdtemp(_stub_dir)) ck_abort_msg("mkdtemp failed");
+
+ snprintf(_record_path, sizeof(_record_path), "%s/record.txt", _stub_dir);
+ snprintf(script_path, sizeof(script_path), "%s/%s", _stub_dir, cmd_name);
+
+ f = fopen(script_path, "w");
+ ck_assert(f != NULL);
+ fprintf(f, "#!/bin/sh\n");
+ fprintf(f, "echo \"$@\" > %s\n", _record_path);
+ fclose(f);
+ ck_assert(chmod(script_path, 0755) == 0);
+
+ /* Save and prepend PATH */
+ cur = getenv("PATH");
+ snprintf(_saved_path, sizeof(_saved_path), "%s", cur ? cur : "");
+ snprintf(new_path, sizeof(new_path), "%s:%s", _stub_dir, _saved_path);
+ setenv("PATH", new_path, 1);
+}
+
+static void
+_cleanup_stub(const char *cmd_name)
+{
+ char script_path[512];
+ snprintf(script_path, sizeof(script_path), "%s/%s", _stub_dir, cmd_name);
+ unlink(script_path);
+ unlink(_record_path);
+ rmdir(_stub_dir);
+ setenv("PATH", _saved_path, 1);
+ _current_stub_cmd[0] = '\0';
+}
+
+static int
+_read_record(char *out, size_t out_sz)
+{
+ FILE *f;
+ size_t n;
+
+ f = fopen(_record_path, "r");
+ if (!f) return -1;
+ n = fread(out, 1, out_sz - 1, f);
+ fclose(f);
+ if (n == 0) return -1;
+ out[n] = '\0';
+ /* Trim trailing newline */
+ if (out[n - 1] == '\n') out[n - 1] = '\0';
+ return 0;
+}
+
+EFL_START_TEST(elm_open_url_rejects_null_and_empty)
+{
+ ck_assert(elm_open_url(NULL) == EINA_FALSE);
+ ck_assert(elm_open_url("") == EINA_FALSE);
+ ck_assert(elm_open_file(NULL) == EINA_FALSE);
+ ck_assert(elm_open_file("") == EINA_FALSE);
+ ck_assert(elm_open_email(NULL)== EINA_FALSE);
+ ck_assert(elm_open_email("") == EINA_FALSE);
+}
+EFL_END_TEST
+
+EFL_START_TEST(elm_open_url_invokes_correct_helper)
+{
+ const char *expected_cmd;
+ char record[1024] = {0};
+ int tries;
+
+#if defined(__APPLE__)
+ expected_cmd = "open";
+#else
+ expected_cmd = "xdg-open";
+#endif
+
+ _install_stub(expected_cmd);
+
+ ck_assert(elm_open_url("https://example.invalid/path") == EINA_TRUE);
+
+ /* ecore_exe_run is async; poll for the record file to appear */
+ for (tries = 0; tries < 50; tries++)
+ {
+ if (_read_record(record, sizeof(record)) == 0) break;
+ usleep(20 * 1000); /* 20ms */
+ ecore_main_loop_iterate();
+ }
+ ck_assert_msg(tries < 50, "Stub helper was not invoked");
+
+ /* Record should contain the URL (escaping may add quotes) */
+ ck_assert_msg(strstr(record, "example.invalid") != NULL,
+ "Record '%s' missing URL", record);
+
+ _cleanup_stub(expected_cmd);
+}
+EFL_END_TEST
+
+EFL_START_TEST(elm_open_file_invokes_correct_helper)
+{
+ const char *expected_cmd;
+ char record[1024] = {0};
+ int tries;
+
+#if defined(__APPLE__)
+ expected_cmd = "open";
+#else
+ expected_cmd = "xdg-open";
+#endif
+
+ _install_stub(expected_cmd);
+
+ ck_assert(elm_open_file("/tmp/elm_open_test_target.txt") == EINA_TRUE);
+
+ /* ecore_exe_run is async; poll for the record file to appear */
+ for (tries = 0; tries < 50; tries++)
+ {
+ if (_read_record(record, sizeof(record)) == 0) break;
+ usleep(20 * 1000);
+ ecore_main_loop_iterate();
+ }
+ ck_assert_msg(tries < 50, "Stub helper was not invoked");
+
+ ck_assert_msg(strstr(record, "elm_open_test_target.txt") != NULL,
+ "Record '%s' missing path", record);
+
+ _cleanup_stub(expected_cmd);
+}
+EFL_END_TEST
+
+EFL_START_TEST(elm_open_email_invokes_correct_helper)
+{
+ const char *expected_cmd;
+ char record[1024] = {0};
+ int tries;
+
+#if defined(__APPLE__)
+ expected_cmd = "open"; /* macOS uses open with mailto: */
+#else
+ expected_cmd = "xdg-email";
+#endif
+
+ _install_stub(expected_cmd);
+
+ ck_assert(elm_open_email("[email protected]") == EINA_TRUE);
+
+ for (tries = 0; tries < 50; tries++)
+ {
+ if (_read_record(record, sizeof(record)) == 0) break;
+ usleep(20 * 1000);
+ ecore_main_loop_iterate();
+ }
+ ck_assert_msg(tries < 50, "Stub helper was not invoked");
+
+ ck_assert_msg(strstr(record, "[email protected]") != NULL,
+ "Record '%s' missing recipient", record);
+
+ _cleanup_stub(expected_cmd);
+}
+EFL_END_TEST
+
+/* Auto-teardown: runs even when ck_assert longjmps out of a test.
+ * Restores PATH and removes the temp dir. */
+static void
+_test_teardown(void)
+{
+ if (_current_stub_cmd[0])
+ _cleanup_stub(_current_stub_cmd);
+}
+
+static void
+_test_setup(void)
+{
+ /* Nothing to do — _install_stub is called explicitly per test. */
+}
+
+void elm_test_open(TCase *tc)
+{
+ tcase_add_checked_fixture(tc, _test_setup, _test_teardown);
+ tcase_add_test(tc, elm_open_url_rejects_null_and_empty);
+ tcase_add_test(tc, elm_open_url_invokes_correct_helper);
+ tcase_add_test(tc, elm_open_file_invokes_correct_helper);
+ tcase_add_test(tc, elm_open_email_invokes_correct_helper);
+}
diff --git a/src/tests/elementary/meson.build b/src/tests/elementary/meson.build
index 3a6257895b..a25e3e6fad 100644
--- a/src/tests/elementary/meson.build
+++ b/src/tests/elementary/meson.build
@@ -75,6 +75,7 @@ elementary_suite_src = [
'elm_test_hoversel.c',
'elm_test_multibuttonentry.c',
'elm_test_naviframe.c',
+ 'elm_test_open.c',
'elm_test_popup.c',
'elm_test_bubble.c',
'elm_test_clock.c',
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.