[dconf: 2/3] Tests: replace usage of dlsym with separate modules containing functions that need to be mocked out



commit 8cbaee1c341b97d81fc597a4571b459baaac5c11
Author: Daniel Playfair Cal <daniel playfair cal gmail com>
Date:   Mon Jan 7 22:33:15 2019 +1100

    Tests: replace usage of dlsym with separate modules containing functions that need to be mocked out

 engine/dconf-engine-mockable.c | 39 +++++++++++++++++++++++++++++++++++++++
 engine/dconf-engine-mockable.h | 30 ++++++++++++++++++++++++++++++
 engine/dconf-engine-profile.c  |  9 +++++----
 engine/meson.build             | 20 +++++++++++++++++++-
 shm/dconf-shm-mockable.c       | 40 ++++++++++++++++++++++++++++++++++++++++
 shm/dconf-shm-mockable.h       | 31 +++++++++++++++++++++++++++++++
 shm/dconf-shm.c                |  5 +++--
 shm/meson.build                | 22 +++++++++++++++++++++-
 tests/engine.c                 |  9 +++------
 tests/meson.build              |  4 ++--
 tests/shm.c                    | 16 +++-------------
 11 files changed, 196 insertions(+), 29 deletions(-)
---
diff --git a/engine/dconf-engine-mockable.c b/engine/dconf-engine-mockable.c
new file mode 100644
index 0000000..dce2f43
--- /dev/null
+++ b/engine/dconf-engine-mockable.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2019 Daniel Playfair Cal
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the licence, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daniel Playfair Cal <daniel playfair cal gmail com>
+ */
+
+/**
+ * This module contains the production implementations of methods used in
+ * dconf_shm that need to be mocked out for tests.
+ *
+ * In some cases, external methods are wrapped with a different name. This is
+ * done so that it is not necessary to redefine the external functions in
+ * unit tests in order to mock them out, and therefore easy to also call the
+ * non mocked versions in tests if necessary.
+ */
+
+#include "config.h"
+
+#include "dconf-engine-mockable.h"
+
+
+FILE *
+dconf_engine_fopen (const char *pathname, const char *mode)
+{
+  return fopen (pathname, mode);
+}
diff --git a/engine/dconf-engine-mockable.h b/engine/dconf-engine-mockable.h
new file mode 100644
index 0000000..091f6d3
--- /dev/null
+++ b/engine/dconf-engine-mockable.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright © 2019 Daniel Playfair Cal
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the licence, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daniel Playfair Cal <daniel playfair cal gmail com>
+ */
+
+#ifndef __dconf_engine_mockable_h__
+#define __dconf_engine_mockable_h__
+
+#include <gio/gio.h>
+#include <stdio.h>
+
+G_GNUC_INTERNAL
+FILE *dconf_engine_fopen    (const char *pathname,
+                             const char *mode);
+
+#endif
diff --git a/engine/dconf-engine-profile.c b/engine/dconf-engine-profile.c
index b204bb4..6474248 100644
--- a/engine/dconf-engine-profile.c
+++ b/engine/dconf-engine-profile.c
@@ -21,6 +21,7 @@
 #include "config.h"
 
 #include "dconf-engine-profile.h"
+#include "dconf-engine-mockable.h"
 
 #include <string.h>
 #include <stdio.h>
@@ -207,7 +208,7 @@ dconf_engine_open_profile_file (const gchar *profile)
       gchar *filename;
 
       filename = g_build_filename (prefix, "dconf/profile", profile, NULL);
-      fp = fopen (filename, "r");
+      fp = dconf_engine_fopen (filename, "r");
 
       /* If it wasn't ENOENT then we don't want to continue on to check
        * other paths.  Fail immediately.
@@ -236,7 +237,7 @@ dconf_engine_open_mandatory_profile (void)
   memcpy (path, MANDATORY_DIR, mdlen);
   snprintf (path + mdlen, 20, "%u", (guint) getuid ());
 
-  return fopen (path, "r");
+  return dconf_engine_fopen (path, "r");
 }
 
 static FILE *
@@ -253,7 +254,7 @@ dconf_engine_open_runtime_profile (void)
   memcpy (path, runtime_dir, rdlen);
   memcpy (path + rdlen, RUNTIME_PROFILE, sizeof RUNTIME_PROFILE);
 
-  return fopen (path, "r");
+  return dconf_engine_fopen (path, "r");
 }
 
 DConfEngineSource **
@@ -311,7 +312,7 @@ dconf_engine_profile_open (const gchar *profile,
       if (profile[0] != '/')
         file = dconf_engine_open_profile_file (profile);
       else
-        file = fopen (profile, "r");
+        file = dconf_engine_fopen (profile, "r");
     }
 
   if (file != NULL)
diff --git a/engine/meson.build b/engine/meson.build
index d1a959d..ca46b60 100644
--- a/engine/meson.build
+++ b/engine/meson.build
@@ -1,4 +1,4 @@
-sources = files(
+testable_sources = files(
   'dconf-engine.c',
   'dconf-engine-profile.c',
   'dconf-engine-source.c',
@@ -8,6 +8,10 @@ sources = files(
   'dconf-engine-source-system.c',
 )
 
+sources = testable_sources + files(
+  'dconf-engine-mockable.c',
+)
+
 engine_deps = [
   libdconf_common_dep,
   libgvdb_dep,
@@ -26,3 +30,17 @@ libdconf_engine_dep = declare_dependency(
   dependencies: engine_deps,
   link_with: libdconf_engine,
 )
+
+libdconf_engine_test = static_library(
+  'dconf-engine-test',
+  sources: testable_sources,
+  include_directories: top_inc,
+  dependencies: engine_deps + [libdconf_shm_dep],
+  c_args: dconf_c_args,
+  pic: true,
+)
+
+libdconf_engine_test_dep = declare_dependency(
+  dependencies: engine_deps,
+  link_with: libdconf_engine_test,
+)
diff --git a/shm/dconf-shm-mockable.c b/shm/dconf-shm-mockable.c
new file mode 100644
index 0000000..6adf7d5
--- /dev/null
+++ b/shm/dconf-shm-mockable.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2019 Daniel Playfair Cal
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the licence, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daniel Playfair Cal <daniel playfair cal gmail com>
+ */
+
+/**
+ * This module contains the production implementations of methods used in
+ * dconf_shm that need to be mocked out for tests.
+ *
+ * In some cases, external methods are wrapped with a different name. This is
+ * done so that it is not necessary to redefine the external functions in
+ * unit tests in order to mock them out, and therefore easy to also call the
+ * non mocked versions in tests if necessary.
+ */
+
+#include "config.h"
+
+#include "dconf-shm-mockable.h"
+
+#include <unistd.h>
+
+ssize_t
+dconf_shm_pwrite (int fd, const void *buf, size_t count, off_t offset)
+{
+  return pwrite (fd, buf, count, offset);
+}
diff --git a/shm/dconf-shm-mockable.h b/shm/dconf-shm-mockable.h
new file mode 100644
index 0000000..98ff33f
--- /dev/null
+++ b/shm/dconf-shm-mockable.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright © 2019 Daniel Playfair Cal
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the licence, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daniel Playfair Cal <daniel playfair cal gmail com>
+ */
+
+#ifndef __dconf_shm_mockable_h__
+#define __dconf_shm_mockable_h__
+
+#include <glib.h>
+
+G_GNUC_INTERNAL
+ssize_t                 dconf_shm_pwrite   (int          fd,
+                                            const void  *buf,
+                                            size_t       count,
+                                            off_t        offset);
+
+#endif /* __dconf_shm_mockable_h__ */
diff --git a/shm/dconf-shm.c b/shm/dconf-shm.c
index ae8c1c7..dbde759 100644
--- a/shm/dconf-shm.c
+++ b/shm/dconf-shm.c
@@ -21,6 +21,7 @@
 #include "config.h"
 
 #include "dconf-shm.h"
+#include "dconf-shm-mockable.h"
 
 #include <sys/mman.h>
 #include <unistd.h>
@@ -82,7 +83,7 @@ dconf_shm_open (const gchar *name)
    * By writing to the second byte in the file we ensure we don't
    * overwrite the first byte (which is the one we care about).
    */
-  if (pwrite (fd, "", 1, 1) != 1)
+  if (dconf_shm_pwrite (fd, "", 1, 1) != 1)
     {
       g_critical ("failed to allocate file '%s': %s.  dconf will not work properly.", filename, g_strerror 
(errno));
       goto out;
@@ -124,7 +125,7 @@ dconf_shm_flag (const gchar *name)
        * If this fails then it will probably fail for the client too.
        * If it doesn't then there's not really much we can do...
        */
-      if (pwrite (fd, "", 1, 1) == 1)
+      if (dconf_shm_pwrite (fd, "", 1, 1) == 1)
         {
           guint8 *shm;
 
diff --git a/shm/meson.build b/shm/meson.build
index 5fb9fe2..07f77d0 100644
--- a/shm/meson.build
+++ b/shm/meson.build
@@ -1,6 +1,11 @@
+sources = files(
+  'dconf-shm.c',
+  'dconf-shm-mockable.c',
+)
+
 libdconf_shm = static_library(
   'dconf-shm',
-  sources: 'dconf-shm.c',
+  sources: sources,
   include_directories: top_inc,
   dependencies: glib_dep,
   c_args: dconf_c_args,
@@ -11,3 +16,18 @@ libdconf_shm_dep = declare_dependency(
   dependencies: glib_dep,
   link_with: libdconf_shm,
 )
+
+
+libdconf_shm_test = static_library(
+  'dconf-shm-test',
+  sources: 'dconf-shm.c',
+  include_directories: top_inc,
+  dependencies: glib_dep,
+  c_args: dconf_c_args,
+  pic: true,
+)
+
+libdconf_shm_test_dep = declare_dependency(
+  dependencies: glib_dep,
+  link_with: libdconf_shm,
+)
diff --git a/tests/engine.c b/tests/engine.c
index 7f2a748..fd2a348 100644
--- a/tests/engine.c
+++ b/tests/engine.c
@@ -2,6 +2,7 @@
 
 #include "../engine/dconf-engine.h"
 #include "../engine/dconf-engine-profile.h"
+#include "../engine/dconf-engine-mockable.h"
 #include "../common/dconf-enums.h"
 #include "dconf-mock.h"
 
@@ -17,13 +18,9 @@ static const gchar *filename_to_replace;
 static const gchar *filename_to_replace_it_with;
 
 FILE *
-fopen (const char *filename,
+dconf_engine_fopen (const char *filename,
        const char *mode)
 {
-  static FILE * (*real_fopen) (const char *, const char *);
-
-  if (!real_fopen)
-    real_fopen = dlsym (RTLD_NEXT, "fopen");
 
   if (filename_to_replace && g_str_equal (filename, filename_to_replace))
     {
@@ -32,7 +29,7 @@ fopen (const char *filename,
       filename = filename_to_replace_it_with;
     }
 
-  return (* real_fopen) (filename, mode);
+  return fopen (filename, mode);
 }
 
 static void assert_no_messages (void);
diff --git a/tests/meson.build b/tests/meson.build
index 247ad76..8aa5837 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -24,11 +24,11 @@ unit_tests = [
   # [name, sources, c_args, dependencies, link_with]
   ['paths', 'paths.c', [], libdconf_common_dep, []],
   ['changeset', 'changeset.c', [], libdconf_common_dep, []],
-  ['shm', ['shm.c', 'tmpdir.c'], [], [dl_dep, libdconf_common_dep, libdconf_shm_dep], []],
+  ['shm', ['shm.c', 'tmpdir.c'], [], [dl_dep, libdconf_common_dep, libdconf_shm_test_dep], []],
   ['gvdb', 'gvdb.c', '-DSRCDIR="@0@"'.format(test_dir), libgvdb_dep, []],
   ['gdbus-thread', 'dbus.c', '-DDBUS_BACKEND="/gdbus/thread"', libdconf_gdbus_thread_dep, []],
   ['gdbus-filter', 'dbus.c', '-DDBUS_BACKEND="/gdbus/filter"', libdconf_gdbus_filter_dep, []],
-  ['engine', 'engine.c', '-DSRCDIR="@0@"'.format(test_dir), [dl_dep, libdconf_engine_dep, m_dep], 
libdconf_mock],
+  ['engine', 'engine.c', '-DSRCDIR="@0@"'.format(test_dir), [dl_dep, libdconf_engine_test_dep, m_dep], 
libdconf_mock],
   ['client', 'client.c', '-DSRCDIR="@0@"'.format(test_dir), [libdconf_client_dep, libdconf_engine_dep], 
libdconf_mock],
   ['writer', 'writer.c', '-DSRCDIR="@0@"'.format(test_dir), [glib_dep, dl_dep, m_dep, libdconf_service_dep], 
[libdconf_mock]],
 ]
diff --git a/tests/shm.c b/tests/shm.c
index 26c5160..69d683f 100644
--- a/tests/shm.c
+++ b/tests/shm.c
@@ -10,6 +10,7 @@
 #include <dlfcn.h>
 
 #include "../shm/dconf-shm.h"
+#include "../shm/dconf-shm-mockable.h"
 #include "tmpdir.h"
 
 static void
@@ -87,29 +88,18 @@ test_flag_nonexistent (void)
   dconf_shm_flag ("does-not-exist");
 }
 
-#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
-#define PWRITE_SYM "pwrite64"
-#else
-#define PWRITE_SYM "pwrite"
-#endif
-
 static gboolean should_fail_pwrite;
 /* interpose */
 ssize_t
-pwrite (int fd, const void *buf, size_t count, off_t offset)
+dconf_shm_pwrite (int fd, const void *buf, size_t count, off_t offset)
 {
-  static ssize_t (* real_pwrite) (int, const void *, size_t, off_t);
-
-  if (!real_pwrite)
-    real_pwrite = dlsym (RTLD_NEXT, PWRITE_SYM);
-
   if (should_fail_pwrite)
     {
       errno = ENOSPC;
       return -1;
     }
 
-  return (* real_pwrite) (fd, buf, count, offset);
+  return pwrite (fd, buf, count, offset);
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]