Browse Source

Ticket #4584: re-implement mocking via weak symbols instead of symbol duplication

Signed-off-by: Yury V. Zaytsev <yury@shurup.com>
Yury V. Zaytsev 7 months ago
parent
commit
93b539444b
10 changed files with 111 additions and 33 deletions
  1. 1 0
      configure.ac
  2. 7 0
      lib/global.h
  3. 3 3
      lib/mcconfig.h
  4. 2 1
      lib/tty/tty-ncurses.c
  5. 4 3
      lib/tty/tty.c
  6. 14 2
      lib/util.h
  7. 71 16
      lib/utilunix.c
  8. 2 1
      lib/vfs/netutil.c
  9. 1 1
      lib/vfs/utilvfs.h
  10. 6 6
      lib/vfs/vfs.c

+ 1 - 0
configure.ac

@@ -65,6 +65,7 @@ dnl which causes attribute checks to fail
 ax_gcc_func_attribute_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
 _AC_LANG_PREFIX[]FLAGS=
 AX_GCC_FUNC_ATTRIBUTE([fallthrough])
+AX_GCC_FUNC_ATTRIBUTE([weak])
 _AC_LANG_PREFIX[]FLAGS=$ax_gcc_func_attribute_save_flags
 unset ax_gcc_func_attribute_save_flags
 

+ 7 - 0
lib/global.h

@@ -8,6 +8,13 @@
 #define MC_GLOBAL_H
 
 #include <glib.h>
+
+#if defined(HAVE_FUNC_ATTRIBUTE_WEAK) && defined(HAVE_TESTS)
+#define MC_MOCKABLE __attribute__((weak))
+#else
+#define MC_MOCKABLE
+#endif
+
 #include "glibcompat.h"
 
 #include "unixcompat.h"

+ 3 - 3
lib/mcconfig.h

@@ -53,8 +53,8 @@ gchar **mc_config_get_keys (const mc_config_t * mc_config, const gchar * group,
 
 gchar *mc_config_get_string (mc_config_t * mc_config, const gchar * group, const gchar * param,
                              const gchar * def);
-gchar *mc_config_get_string_raw (mc_config_t * mc_config, const gchar * group, const gchar * param,
-                                 const gchar * def);
+MC_MOCKABLE gchar *mc_config_get_string_raw (mc_config_t * mc_config, const gchar * group,
+                                             const gchar * param, const gchar * def);
 gboolean mc_config_get_bool (mc_config_t * mc_config, const gchar * group, const gchar * param,
                              gboolean def);
 int mc_config_get_int (mc_config_t * mc_config, const gchar * group, const gchar * param, int def);
@@ -96,7 +96,7 @@ void mc_config_deinit_config_paths (void);
 
 const char *mc_config_get_data_path (void);
 const char *mc_config_get_cache_path (void);
-const char *mc_config_get_home_dir (void);
+MC_MOCKABLE const char *mc_config_get_home_dir (void);
 const char *mc_config_get_path (void);
 char *mc_config_get_full_path (const char *config_name);
 vfs_path_t *mc_config_get_full_vpath (const char *config_name);

+ 2 - 1
lib/tty/tty-ncurses.c

@@ -41,6 +41,7 @@
 
 #include "lib/global.h"
 #include "lib/strutil.h"        /* str_term_form */
+#include "lib/util.h"
 
 #ifndef WANT_TERM_H
 #define WANT_TERM_H
@@ -102,7 +103,7 @@ tty_setup_sigwinch (void (*handler) (int))
 #ifdef SA_RESTART
     act.sa_flags = SA_RESTART;
 #endif /* SA_RESTART */
-    sigaction (SIGWINCH, &act, &oact);
+    my_sigaction (SIGWINCH, &act, &oact);
 #endif /* SIGWINCH */
 
     tty_create_winch_pipe ();

+ 4 - 3
lib/tty/tty.c

@@ -53,6 +53,7 @@
 
 #include "lib/global.h"
 #include "lib/strutil.h"
+#include "lib/util.h"
 
 #include "tty.h"
 #include "tty-internal.h"
@@ -146,7 +147,7 @@ tty_start_interrupt_key (void)
 #ifdef SA_RESTART
     act.sa_flags = SA_RESTART;
 #endif /* SA_RESTART */
-    sigaction (SIGINT, &act, NULL);
+    my_sigaction (SIGINT, &act, NULL);
 }
 
 /* --------------------------------------------------------------------------------------------- */
@@ -159,7 +160,7 @@ tty_enable_interrupt_key (void)
     memset (&act, 0, sizeof (act));
     act.sa_handler = sigintr_handler;
     sigemptyset (&act.sa_mask);
-    sigaction (SIGINT, &act, NULL);
+    my_sigaction (SIGINT, &act, NULL);
     got_interrupt = 0;
 }
 
@@ -173,7 +174,7 @@ tty_disable_interrupt_key (void)
     memset (&act, 0, sizeof (act));
     act.sa_handler = SIG_IGN;
     sigemptyset (&act.sa_mask);
-    sigaction (SIGINT, &act, NULL);
+    my_sigaction (SIGINT, &act, NULL);
 }
 
 /* --------------------------------------------------------------------------------------------- */

+ 14 - 2
lib/util.h

@@ -126,6 +126,11 @@ typedef struct
     mc_pipe_stream_t err;
 } mc_pipe_t;
 
+/* sighandler_t is GNU extension */
+#ifndef HAVE_SIGHANDLER_T
+typedef void (*sighandler_t) (int);
+#endif
+
 /*** structures declarations (and typedefs of structures)*****************************************/
 
 /*** global variables defined in .c file *********************************************************/
@@ -200,6 +205,13 @@ const char *get_owner (uid_t uid);
 /* Returns a copy of *s until a \n is found and is below top */
 const char *extract_line (const char *s, const char *top, size_t *len);
 
+/* System call wrappers */
+MC_MOCKABLE sighandler_t my_signal (int signum, sighandler_t handler);
+MC_MOCKABLE int my_sigaction (int signum, const struct sigaction *act, struct sigaction *oldact);
+MC_MOCKABLE pid_t my_fork (void);
+MC_MOCKABLE int my_execvp (const char *file, char *const argv[]);
+MC_MOCKABLE char *my_get_current_dir (void);
+
 /* Process spawning */
 int my_system (int flags, const char *shell, const char *command);
 int my_systeml (int flags, const char *shell, ...);
@@ -212,7 +224,7 @@ void mc_pclose (mc_pipe_t * p, GError ** error);
 
 GString *mc_pstream_get_string (mc_pipe_stream_t * ps);
 
-void my_exit (int status);
+MC_MOCKABLE void my_exit (int status);
 void save_stop_handler (void);
 
 /* Tilde expansion */
@@ -249,7 +261,7 @@ gboolean mc_util_make_backup_if_possible (const char *file_name, const char *bac
 gboolean mc_util_restore_from_backup_if_possible (const char *file_name, const char *backup_suffix);
 gboolean mc_util_unlink_backup_if_possible (const char *file_name, const char *backup_suffix);
 
-char *guess_message_value (void);
+MC_MOCKABLE char *guess_message_value (void);
 
 char *mc_build_filename (const char *first_element, ...);
 char *mc_build_filenamev (const char *first_element, va_list args);

+ 71 - 16
lib/utilunix.c

@@ -137,11 +137,11 @@ i_cache_add (int id, int_cache *cache, int size, char *text, int *last)
 /* --------------------------------------------------------------------------------------------- */
 
 static my_fork_state_t
-my_fork (void)
+my_fork_state (void)
 {
     pid_t pid;
 
-    pid = fork ();
+    pid = my_fork ();
 
     if (pid < 0)
     {
@@ -175,12 +175,12 @@ my_system__save_sigaction_handlers (my_system_sigactions_t *sigactions)
     ignore.sa_handler = SIG_IGN;
     sigemptyset (&ignore.sa_mask);
 
-    sigaction (SIGINT, &ignore, &sigactions->intr);
-    sigaction (SIGQUIT, &ignore, &sigactions->quit);
+    my_sigaction (SIGINT, &ignore, &sigactions->intr);
+    my_sigaction (SIGQUIT, &ignore, &sigactions->quit);
 
     /* Restore the original SIGTSTP handler, we don't want ncurses' */
     /* handler messing the screen after the SIGCONT */
-    sigaction (SIGTSTP, &startup_handler, &sigactions->stop);
+    my_sigaction (SIGTSTP, &startup_handler, &sigactions->stop);
 }
 
 /* --------------------------------------------------------------------------------------------- */
@@ -188,9 +188,9 @@ my_system__save_sigaction_handlers (my_system_sigactions_t *sigactions)
 static void
 my_system__restore_sigaction_handlers (my_system_sigactions_t *sigactions)
 {
-    sigaction (SIGINT, &sigactions->intr, NULL);
-    sigaction (SIGQUIT, &sigactions->quit, NULL);
-    sigaction (SIGTSTP, &sigactions->stop, NULL);
+    my_sigaction (SIGINT, &sigactions->intr, NULL);
+    my_sigaction (SIGQUIT, &sigactions->quit, NULL);
+    my_sigaction (SIGTSTP, &sigactions->stop, NULL);
 }
 
 /* --------------------------------------------------------------------------------------------- */
@@ -329,7 +329,7 @@ get_group (gid_t gid)
 void
 save_stop_handler (void)
 {
-    sigaction (SIGTSTP, NULL, &startup_handler);
+    my_sigaction (SIGTSTP, NULL, &startup_handler);
 }
 
 /* --------------------------------------------------------------------------------------------- */
@@ -348,6 +348,61 @@ my_exit (int status)
     _exit (status);
 }
 
+/* --------------------------------------------------------------------------------------------- */
+/**
+ * Wrapper for signal() system call.
+ */
+
+sighandler_t
+my_signal (int signum, sighandler_t handler)
+{
+    return signal (signum, handler);
+}
+
+/* --------------------------------------------------------------------------------------------- */
+/**
+ * Wrapper for sigaction() system call.
+ */
+
+int
+my_sigaction (int signum, const struct sigaction *act, struct sigaction *oldact)
+{
+    return sigaction (signum, act, oldact);
+}
+
+/* --------------------------------------------------------------------------------------------- */
+/**
+ * Wrapper for fork() system call.
+ */
+
+pid_t
+my_fork (void)
+{
+    return fork ();
+}
+
+/* --------------------------------------------------------------------------------------------- */
+/**
+ * Wrapper for execvp() system call.
+ */
+
+int
+my_execvp (const char *file, char *const argv[])
+{
+    return execvp (file, argv);
+}
+
+/* --------------------------------------------------------------------------------------------- */
+/**
+ * Wrapper for g_get_current_dir() library function.
+ */
+
+char *
+my_get_current_dir (void)
+{
+    return g_get_current_dir ();
+}
+
 /* --------------------------------------------------------------------------------------------- */
 /**
  * Call external programs.
@@ -422,7 +477,7 @@ my_systemv (const char *command, char *const argv[])
 
     my_system__save_sigaction_handlers (&sigactions);
 
-    fork_state = my_fork ();
+    fork_state = my_fork_state ();
     switch (fork_state)
     {
     case FORK_ERROR:
@@ -430,12 +485,12 @@ my_systemv (const char *command, char *const argv[])
         break;
     case FORK_CHILD:
         {
-            signal (SIGINT, SIG_DFL);
-            signal (SIGQUIT, SIG_DFL);
-            signal (SIGTSTP, SIG_DFL);
-            signal (SIGCHLD, SIG_DFL);
+            my_signal (SIGINT, SIG_DFL);
+            my_signal (SIGQUIT, SIG_DFL);
+            my_signal (SIGTSTP, SIG_DFL);
+            my_signal (SIGCHLD, SIG_DFL);
 
-            execvp (command, argv);
+            my_execvp (command, argv);
             my_exit (127);      /* Exec error */
         }
         MC_FALLTHROUGH;
@@ -1056,7 +1111,7 @@ mc_realpath (const char *path, char *resolved_path)
         /* If it's a relative pathname use getwd for starters. */
         if (!IS_PATH_SEP (*path))
         {
-            new_path = g_get_current_dir ();
+            new_path = my_get_current_dir ();
             if (new_path == NULL)
                 strcpy (got_path, "");
             else

+ 2 - 1
lib/vfs/netutil.c

@@ -32,6 +32,7 @@
 #include <string.h>             /* memset() */
 
 #include "lib/global.h"
+#include "lib/util.h"
 
 #include "netutil.h"
 
@@ -75,7 +76,7 @@ tcp_init (void)
     memset (&sa, 0, sizeof (sa));
     sa.sa_handler = sig_pipe;
     sigemptyset (&sa.sa_mask);
-    sigaction (SIGPIPE, &sa, NULL);
+    my_sigaction (SIGPIPE, &sa, NULL);
 
     initialized = TRUE;
 }

+ 1 - 1
lib/vfs/utilvfs.h

@@ -43,7 +43,7 @@ vfs_path_element_t *vfs_url_split (const char *path, int default_port, vfs_url_f
 int vfs_split_text (char *p);
 
 int vfs_mkstemps (vfs_path_t ** pname_vpath, const char *prefix, const char *basename);
-void vfs_die (const char *msg);
+MC_MOCKABLE void vfs_die (const char *msg);
 char *vfs_get_password (const char *msg);
 
 char *vfs_get_local_username (void);

+ 6 - 6
lib/vfs/vfs.c

@@ -77,10 +77,10 @@ extern vfs_class *current_vfs;
 
 /*** global variables ****************************************************************************/
 
-struct vfs_dirent *mc_readdir_result = NULL;
-GPtrArray *vfs__classes_list = NULL;
-GString *vfs_str_buffer = NULL;
-vfs_class *current_vfs = NULL;
+MC_MOCKABLE struct vfs_dirent *mc_readdir_result = NULL;
+MC_MOCKABLE GPtrArray *vfs__classes_list = NULL;
+MC_MOCKABLE GString *vfs_str_buffer = NULL;
+MC_MOCKABLE vfs_class *current_vfs = NULL;
 
 /*** file scope macro definitions ****************************************************************/
 
@@ -638,7 +638,7 @@ vfs_setup_cwd (void)
 
     if (vfs_get_raw_current_dir () == NULL)
     {
-        current_dir = g_get_current_dir ();
+        current_dir = my_get_current_dir ();
         vfs_set_raw_current_dir (vfs_path_from_str (current_dir));
         g_free (current_dir);
 
@@ -657,7 +657,7 @@ vfs_setup_cwd (void)
     me = vfs_path_get_last_path_vfs (vfs_get_raw_current_dir ());
     if ((me->flags & VFSF_LOCAL) != 0)
     {
-        current_dir = g_get_current_dir ();
+        current_dir = my_get_current_dir ();
         tmp_vpath = vfs_path_from_str (current_dir);
         g_free (current_dir);
 

Some files were not shown because too many files changed in this diff