diff options
author | Daniel Playfair Cal <daniel.playfair.cal@gmail.com> | 2019-02-12 22:17:20 +0000 |
---|---|---|
committer | Daniel Playfair Cal <daniel.playfair.cal@gmail.com> | 2019-02-12 22:17:20 +0000 |
commit | b62ce371159be9f518657ec907b668d91287e7c8 (patch) | |
tree | 1e8171e23490d3cca27c18494454b344724e3bc8 | |
parent | 0740fd9c28f5cb2cfab634ebdd3c6f4893e2d296 (diff) | |
parent | 8cbaee1c341b97d81fc597a4571b459baaac5c11 (diff) | |
download | dconf-b62ce371159be9f518657ec907b668d91287e7c8.tar.gz |
Merge branch 'fix-shm-test-modules' into 'master'
Tests: remove bug prone usage of dlsym and RTDL_NEXT
See merge request GNOME/dconf!37
-rw-r--r-- | engine/dconf-engine-mockable.c | 39 | ||||
-rw-r--r-- | engine/dconf-engine-mockable.h | 30 | ||||
-rw-r--r-- | engine/dconf-engine-profile.c | 9 | ||||
-rw-r--r-- | engine/meson.build | 20 | ||||
-rw-r--r-- | shm/dconf-shm-mockable.c | 40 | ||||
-rw-r--r-- | shm/dconf-shm-mockable.h | 31 | ||||
-rw-r--r-- | shm/dconf-shm.c | 5 | ||||
-rw-r--r-- | shm/meson.build | 22 | ||||
-rw-r--r-- | tests/engine.c | 9 | ||||
-rw-r--r-- | tests/meson.build | 4 | ||||
-rw-r--r-- | tests/shm.c | 10 |
11 files changed, 196 insertions, 23 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 a0cf67e..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 @@ -90,20 +91,15 @@ test_flag_nonexistent (void) 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"); - if (should_fail_pwrite) { errno = ENOSPC; return -1; } - return (* real_pwrite) (fd, buf, count, offset); + return pwrite (fd, buf, count, offset); } static void |