diff options
author | Thomas Haller <thaller@redhat.com> | 2023-01-17 16:27:41 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2023-01-17 16:27:41 +0100 |
commit | a45029b7b0e83f17553d5041ee6fa84ff13cb289 (patch) | |
tree | f93f38ab9635238b94500118fbcda3b695c88388 | |
parent | 3cd02b6ed6e75319a5abee1a6716e90836ef30b8 (diff) | |
parent | 5d81b472dca61a13a5c7bb555536500e80d8478c (diff) |
tests: merge branch 'th/leak-test-data'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1492
-rw-r--r-- | src/libnm-glib-aux/nm-dedup-multi.c | 15 | ||||
-rw-r--r-- | src/libnm-glib-aux/nm-test-utils.h | 157 |
2 files changed, 137 insertions, 35 deletions
diff --git a/src/libnm-glib-aux/nm-dedup-multi.c b/src/libnm-glib-aux/nm-dedup-multi.c index 7d451d0d35..625c4ef31e 100644 --- a/src/libnm-glib-aux/nm-dedup-multi.c +++ b/src/libnm-glib-aux/nm-dedup-multi.c @@ -1004,12 +1004,14 @@ nm_dedup_multi_index_new(void) { NMDedupMultiIndex *self; - self = g_slice_new0(NMDedupMultiIndex); - self->ref_count = 1; - self->idx_entries = - g_hash_table_new((GHashFunc) _dict_idx_entries_hash, (GEqualFunc) _dict_idx_entries_equal); - self->idx_objs = - g_hash_table_new((GHashFunc) _dict_idx_objs_hash, (GEqualFunc) _dict_idx_objs_equal); + self = g_slice_new(NMDedupMultiIndex); + *self = (NMDedupMultiIndex){ + .ref_count = 1, + .idx_entries = g_hash_table_new((GHashFunc) _dict_idx_entries_hash, + (GEqualFunc) _dict_idx_entries_equal), + .idx_objs = + g_hash_table_new((GHashFunc) _dict_idx_objs_hash, (GEqualFunc) _dict_idx_objs_equal), + }; return self; } @@ -1018,6 +1020,7 @@ nm_dedup_multi_index_ref(NMDedupMultiIndex *self) { g_return_val_if_fail(self, NULL); g_return_val_if_fail(self->ref_count > 0, NULL); + nm_assert(self->ref_count < G_MAXINT32); self->ref_count++; return self; diff --git a/src/libnm-glib-aux/nm-test-utils.h b/src/libnm-glib-aux/nm-test-utils.h index 3e7a122125..5196c9a076 100644 --- a/src/libnm-glib-aux/nm-test-utils.h +++ b/src/libnm-glib-aux/nm-test-utils.h @@ -224,17 +224,24 @@ /*****************************************************************************/ +struct __nmtst_testdata_track { + gpointer data; + GDestroyNotify destroy_notify; +}; + struct __nmtst_internal { - GRand *rand0; - guint32 rand_seed; - GRand *rand; - gboolean is_debug; - gboolean assert_logging; - gboolean no_expect_message; - gboolean test_quick; - gboolean test_tap_log; - char *sudo_cmd; - char **orig_argv; + GRand *rand0; + guint32 rand_seed; + GRand *rand; + gboolean is_debug; + gboolean assert_logging; + gboolean no_expect_message; + gboolean test_quick; + gboolean test_tap_log; + char *sudo_cmd; + char **orig_argv; + const char *testpath; + GArray *testdata_track_array; }; extern struct __nmtst_internal __nmtst_internal; @@ -255,6 +262,62 @@ nmtst_initialized(void) return !!__nmtst_internal.rand0; } +/*****************************************************************************/ + +static inline void +_nmtst_testdata_track_clear_func(gpointer ptr) +{ + struct __nmtst_testdata_track *d = ptr; + + if (d->destroy_notify) + d->destroy_notify(d->data); + memset(d, 0, sizeof(*d)); +} + +static inline void +_nmtst_testdata_track_add(gpointer data, GDestroyNotify destroy_notify) +{ + struct __nmtst_testdata_track d = { + .data = data, + .destroy_notify = destroy_notify, + }; + + g_assert(data); + g_assert(destroy_notify); + g_assert(__nmtst_internal.testdata_track_array); + + g_array_append_val(__nmtst_internal.testdata_track_array, d); +} + +static inline void +_nmtst_testdata_track_steal(gpointer data) +{ + struct __nmtst_testdata_track *d; + guint i; + + g_assert(data); + g_assert(__nmtst_internal.testdata_track_array); + + for (i = 0; i < __nmtst_internal.testdata_track_array->len; i++) { + d = &g_array_index(__nmtst_internal.testdata_track_array, struct __nmtst_testdata_track, i); + + if (d->data != data) + continue; + + d->destroy_notify = NULL; + g_array_remove_index_fast(__nmtst_internal.testdata_track_array, i); + return; + } + g_assert_not_reached(); +} + +static inline void +_nmtst_testdata_track_steal_and_free(gpointer data) +{ + _nmtst_testdata_track_steal(data); + g_free(data); +} + #define __NMTST_LOG(cmd, ...) \ G_STMT_START \ { \ @@ -323,6 +386,9 @@ nmtst_free(void) if (!nmtst_initialized()) return; + g_array_set_size(__nmtst_internal.testdata_track_array, 0); + g_array_unref(__nmtst_internal.testdata_track_array); + g_rand_free(__nmtst_internal.rand0); if (__nmtst_internal.rand) g_rand_free(__nmtst_internal.rand); @@ -579,6 +645,10 @@ __nmtst_init(int *argc, __nmtst_internal.sudo_cmd = sudo_cmd; __nmtst_internal.no_expect_message = no_expect_message; + __nmtst_internal.testdata_track_array = + g_array_new(FALSE, FALSE, sizeof(struct __nmtst_testdata_track)); + g_array_set_clear_func(__nmtst_internal.testdata_track_array, _nmtst_testdata_track_clear_func); + if (!log_level && log_domains) { /* if the log level is not specified (but the domain is), we assume * the caller wants to set it depending on is_debug */ @@ -777,15 +847,12 @@ typedef struct _NmtstTestData NmtstTestData; typedef void (*NmtstTestHandler)(const NmtstTestData *test_data); struct _NmtstTestData { - union { - const char *testpath; - char *_testpath; - }; + const char *testpath; gsize n_args; - gpointer *args; NmtstTestHandler _func_setup; GTestDataFunc _func_test; NmtstTestHandler _func_teardown; + gpointer args[]; }; static inline void @@ -810,15 +877,20 @@ _nmtst_test_data_unpack(const NmtstTestData *test_data, gsize n_args, ...) #define nmtst_test_data_unpack(test_data, ...) \ _nmtst_test_data_unpack(test_data, NM_NARG(__VA_ARGS__), ##__VA_ARGS__) -static inline void -_nmtst_test_data_free(gpointer data) +static inline const char * +nmtst_test_get_path(void) { - NmtstTestData *test_data = data; + g_assert(nmtst_initialized()); + g_assert(__nmtst_internal.testpath); - g_assert(test_data); + /* Similar to g_test_get_path() (which only exists since glib 2.68). + * + * This is the test name while running the test added with + * nmtst_add_test_func*(). + * + * You are only allowed to call this from inside such a test. */ - g_free(test_data->_testpath); - g_free(test_data); + return __nmtst_internal.testpath; } static inline void @@ -826,6 +898,13 @@ _nmtst_test_run(gconstpointer data) { const NmtstTestData *test_data = data; + g_assert(test_data); + g_assert(nmtst_initialized()); + g_assert(test_data->testpath); + g_assert(!__nmtst_internal.testpath); + + __nmtst_internal.testpath = test_data->testpath; + if (test_data->_func_setup) test_data->_func_setup(test_data); @@ -833,6 +912,10 @@ _nmtst_test_run(gconstpointer data) if (test_data->_func_teardown) test_data->_func_teardown(test_data); + + g_assert(__nmtst_internal.testpath); + g_assert(__nmtst_internal.testpath == test_data->testpath); + __nmtst_internal.testpath = NULL; } static inline void @@ -846,26 +929,41 @@ _nmtst_add_test_func_full(const char *testpath, gsize i; NmtstTestData *data; va_list ap; + gsize testpath_len; g_assert(testpath && testpath[0]); g_assert(func_test); - data = g_malloc0(sizeof(NmtstTestData) + (sizeof(gpointer) * (n_args + 1))); + testpath_len = strlen(testpath) + 1u; + + data = g_malloc(G_STRUCT_OFFSET(NmtstTestData, args) + + (sizeof(gpointer) * (n_args + 1u) + testpath_len)); + + *data = (NmtstTestData){ + .testpath = (gpointer) &data->args[n_args + 1u], + ._func_test = func_test, + ._func_setup = func_setup, + ._func_teardown = func_teardown, + .n_args = n_args, + }; - data->_testpath = g_strdup(testpath); - data->_func_test = func_test; - data->_func_setup = func_setup; - data->_func_teardown = func_teardown; - data->n_args = n_args; - data->args = (gpointer) &data[1]; va_start(ap, n_args); for (i = 0; i < n_args; i++) data->args[i] = va_arg(ap, gpointer); data->args[i] = NULL; va_end(ap); - g_test_add_data_func_full(testpath, data, _nmtst_test_run, _nmtst_test_data_free); + g_assert(data->testpath == (gpointer) &data->args[i + 1]); + + memcpy((char *) data->testpath, testpath, testpath_len); + + _nmtst_testdata_track_add(data, g_free); + g_test_add_data_func_full(testpath, + data, + _nmtst_test_run, + _nmtst_testdata_track_steal_and_free); } + #define nmtst_add_test_func_full(testpath, func_test, func_setup, func_teardown, ...) \ _nmtst_add_test_func_full(testpath, \ func_test, \ @@ -873,6 +971,7 @@ _nmtst_add_test_func_full(const char *testpath, func_teardown, \ NM_NARG(__VA_ARGS__), \ ##__VA_ARGS__) + #define nmtst_add_test_func(testpath, func_test, ...) \ nmtst_add_test_func_full(testpath, func_test, NULL, NULL, ##__VA_ARGS__) |