summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2023-01-17 16:27:41 +0100
committerThomas Haller <thaller@redhat.com>2023-01-17 16:27:41 +0100
commita45029b7b0e83f17553d5041ee6fa84ff13cb289 (patch)
treef93f38ab9635238b94500118fbcda3b695c88388
parent3cd02b6ed6e75319a5abee1a6716e90836ef30b8 (diff)
parent5d81b472dca61a13a5c7bb555536500e80d8478c (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.c15
-rw-r--r--src/libnm-glib-aux/nm-test-utils.h157
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__)