Blame src/tests/test-core-with-expect.c

Packit Service b23acc
// SPDX-License-Identifier: GPL-2.0+
Packit Service b23acc
/*
Packit Service b23acc
 * Copyright (C) 2014 Red Hat, Inc.
Packit Service b23acc
 */
Packit Service b23acc
Packit Service b23acc
#include "nm-default.h"
Packit Service b23acc
Packit Service b23acc
#include <time.h>
Packit Service b23acc
#include <netinet/ether.h>
Packit Service b23acc
#include <sys/types.h>
Packit Service b23acc
#include <sys/wait.h>
Packit Service b23acc
#include <fcntl.h>
Packit Service b23acc
Packit Service b23acc
#include "NetworkManagerUtils.h"
Packit Service b23acc
Packit Service b23acc
#include "nm-test-utils-core.h"
Packit Service b23acc
Packit Service b23acc
/*****************************************************************************/
Packit Service b23acc
Packit Service b23acc
static void
Packit Service b23acc
test_nm_utils_monotonic_timestamp_as_boottime (void)
Packit Service b23acc
{
Packit Service b23acc
	gint64 timestamp_nsec_per_tick, now, now_boottime, now_boottime_2, now_boottime_3;
Packit Service b23acc
	struct timespec tp;
Packit Service b23acc
	clockid_t clockid;
Packit Service b23acc
	guint i;
Packit Service b23acc
Packit Service b23acc
	if (   clock_gettime (CLOCK_BOOTTIME, &tp) != 0
Packit Service b23acc
	    && errno == EINVAL)
Packit Service b23acc
		clockid = CLOCK_MONOTONIC;
Packit Service b23acc
	else
Packit Service b23acc
		clockid = CLOCK_BOOTTIME;
Packit Service b23acc
Packit Service b23acc
	for (i = 0; i < 10; i++) {
Packit Service b23acc
Packit Service b23acc
		if (clock_gettime (clockid, &tp) != 0)
Packit Service b23acc
			g_assert_not_reached ();
Packit Service b23acc
		now_boottime = ( ((gint64) tp.tv_sec) * NM_UTILS_NSEC_PER_SEC ) + ((gint64) tp.tv_nsec);
Packit Service b23acc
Packit Service b23acc
		now = nm_utils_get_monotonic_timestamp_nsec ();
Packit Service b23acc
Packit Service b23acc
		now_boottime_2 = nm_utils_monotonic_timestamp_as_boottime (now, 1);
Packit Service b23acc
		g_assert_cmpint (now_boottime_2, >=, 0);
Packit Service b23acc
		g_assert_cmpint (now_boottime_2, >=, now_boottime);
Packit Service b23acc
		g_assert_cmpint (now_boottime_2 - now_boottime, <=, NM_UTILS_NSEC_PER_SEC / 10);
Packit Service b23acc
Packit Service b23acc
		g_assert_cmpint (now, ==, nm_utils_monotonic_timestamp_from_boottime (now_boottime_2, 1));
Packit Service b23acc
Packit Service b23acc
		for (timestamp_nsec_per_tick = 1; timestamp_nsec_per_tick <= NM_UTILS_NSEC_PER_SEC; timestamp_nsec_per_tick *= 10) {
Packit Service b23acc
			now_boottime_3 = nm_utils_monotonic_timestamp_as_boottime (now / timestamp_nsec_per_tick, timestamp_nsec_per_tick);
Packit Service b23acc
Packit Service b23acc
			g_assert_cmpint (now_boottime_2 / timestamp_nsec_per_tick, ==, now_boottime_3);
Packit Service b23acc
			g_assert_cmpint (now / timestamp_nsec_per_tick, ==, nm_utils_monotonic_timestamp_from_boottime (now_boottime_3, timestamp_nsec_per_tick));
Packit Service b23acc
		}
Packit Service b23acc
	}
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
/*****************************************************************************/
Packit Service b23acc
Packit Service b23acc
struct test_nm_utils_kill_child_async_data
Packit Service b23acc
{
Packit Service b23acc
	GMainLoop *loop;
Packit Service b23acc
	pid_t pid;
Packit Service b23acc
	gboolean called;
Packit Service b23acc
	gboolean expected_success;
Packit Service b23acc
	const int *expected_child_status;
Packit Service b23acc
};
Packit Service b23acc
Packit Service b23acc
static void
Packit Service b23acc
test_nm_utils_kill_child_async_cb (pid_t pid, gboolean success, int child_status, void *user_data)
Packit Service b23acc
{
Packit Service b23acc
	struct test_nm_utils_kill_child_async_data *data = user_data;
Packit Service b23acc
Packit Service b23acc
	g_assert (success == !!data->expected_success);
Packit Service b23acc
	g_assert (pid == data->pid);
Packit Service b23acc
	if (data->expected_child_status)
Packit Service b23acc
		g_assert_cmpint (*data->expected_child_status, ==, child_status);
Packit Service b23acc
	if (!success)
Packit Service b23acc
		g_assert_cmpint (child_status, ==, -1);
Packit Service b23acc
Packit Service b23acc
	data->called = TRUE;
Packit Service b23acc
Packit Service b23acc
	g_assert (data->loop);
Packit Service b23acc
	g_main_loop_quit (data->loop);
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
static gboolean
Packit Service b23acc
test_nm_utils_kill_child_async_fail_cb (void *user_data)
Packit Service b23acc
{
Packit Service b23acc
	g_assert_not_reached ();
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
static void
Packit Service b23acc
test_nm_utils_kill_child_async_do (const char *name, pid_t pid, int sig, guint32 wait_before_kill_msec, gboolean expected_success, const int *expected_child_status)
Packit Service b23acc
{
Packit Service b23acc
	gboolean success;
Packit Service b23acc
	struct test_nm_utils_kill_child_async_data data = { };
Packit Service b23acc
	int timeout_id;
Packit Service b23acc
Packit Service b23acc
	data.pid = pid;
Packit Service b23acc
	data.expected_success = expected_success;
Packit Service b23acc
	data.expected_child_status = expected_child_status;
Packit Service b23acc
Packit Service b23acc
	nm_utils_kill_child_async (pid, sig, LOGD_CORE, name, wait_before_kill_msec, test_nm_utils_kill_child_async_cb, &data);
Packit Service b23acc
	g_assert (!data.called);
Packit Service b23acc
Packit Service b23acc
	timeout_id = g_timeout_add_seconds (5, test_nm_utils_kill_child_async_fail_cb, &data);
Packit Service b23acc
Packit Service b23acc
	data.loop = g_main_loop_new (NULL, FALSE);
Packit Service b23acc
	g_main_loop_run (data.loop);
Packit Service b23acc
Packit Service b23acc
	g_assert (data.called);
Packit Service b23acc
	success = g_source_remove (timeout_id);
Packit Service b23acc
	g_assert (success);
Packit Service b23acc
Packit Service b23acc
	g_main_loop_unref (data.loop);
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
static void
Packit Service b23acc
test_nm_utils_kill_child_sync_do (const char *name, pid_t pid, int sig, guint32 wait_before_kill_msec, gboolean expected_success, const int *expected_child_status)
Packit Service b23acc
{
Packit Service b23acc
	gboolean success;
Packit Service b23acc
	int child_status = -1;
Packit Service b23acc
Packit Service b23acc
	success = nm_utils_kill_child_sync (pid, sig, LOGD_CORE, name, &child_status, wait_before_kill_msec, 0);
Packit Service b23acc
	g_assert (success == !!expected_success);
Packit Service b23acc
	if (expected_child_status)
Packit Service b23acc
		g_assert_cmpint (*expected_child_status, ==, child_status);
Packit Service b23acc
Packit Service b23acc
	g_test_assert_expected_messages ();
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
static pid_t
Packit Service b23acc
test_nm_utils_kill_child_spawn (char **argv, gboolean do_not_reap_child)
Packit Service b23acc
{
Packit Service b23acc
	GError *error = NULL;
Packit Service b23acc
	int success;
Packit Service b23acc
	GPid child_pid;
Packit Service b23acc
Packit Service b23acc
	success = g_spawn_async (NULL,
Packit Service b23acc
	                         argv,
Packit Service b23acc
	                         NULL,
Packit Service b23acc
	                         G_SPAWN_SEARCH_PATH | (do_not_reap_child ? G_SPAWN_DO_NOT_REAP_CHILD : 0),
Packit Service b23acc
	                         NULL,
Packit Service b23acc
	                         NULL,
Packit Service b23acc
	                         &child_pid,
Packit Service b23acc
	                         &error);
Packit Service b23acc
	g_assert (success && !error);
Packit Service b23acc
	return child_pid;
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
static pid_t
Packit Service b23acc
do_test_nm_utils_kill_child_create_and_join_pgroup (void)
Packit Service b23acc
{
Packit Service b23acc
	int err, tmp = 0;
Packit Service b23acc
	int pipefd[2];
Packit Service b23acc
	pid_t pgid;
Packit Service b23acc
Packit Service b23acc
	err = pipe2 (pipefd, O_CLOEXEC);
Packit Service b23acc
	g_assert (err == 0);
Packit Service b23acc
Packit Service b23acc
	pgid = fork();
Packit Service b23acc
	g_assert (pgid >= 0);
Packit Service b23acc
Packit Service b23acc
	if (pgid == 0) {
Packit Service b23acc
		/* child process... */
Packit Service b23acc
		nm_close (pipefd[0]);
Packit Service b23acc
Packit Service b23acc
		err = setpgid (0, 0);
Packit Service b23acc
		g_assert (err == 0);
Packit Service b23acc
Packit Service b23acc
		err = write (pipefd[1], &tmp, sizeof (tmp));
Packit Service b23acc
		g_assert (err == sizeof (tmp));
Packit Service b23acc
Packit Service b23acc
		nm_close (pipefd[1]);
Packit Service b23acc
		exit (0);
Packit Service b23acc
	}
Packit Service b23acc
Packit Service b23acc
	nm_close (pipefd[1]);
Packit Service b23acc
Packit Service b23acc
	err = read (pipefd[0], &tmp, sizeof (tmp));
Packit Service b23acc
	g_assert (err == sizeof (tmp));
Packit Service b23acc
Packit Service b23acc
	nm_close (pipefd[0]);
Packit Service b23acc
Packit Service b23acc
	err = setpgid (0, pgid);
Packit Service b23acc
	g_assert (err == 0);
Packit Service b23acc
Packit Service b23acc
	do {
Packit Service b23acc
		err = waitpid (pgid, &tmp, 0);
Packit Service b23acc
	} while (err == -1 && errno == EINTR);
Packit Service b23acc
	g_assert (err == pgid);
Packit Service b23acc
	g_assert (WIFEXITED (tmp) && WEXITSTATUS(tmp) == 0);
Packit Service b23acc
Packit Service b23acc
	return pgid;
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
#define TEST_TOKEN  "nm_test_kill_child_process"
Packit Service b23acc
Packit Service b23acc
static void
Packit Service b23acc
do_test_nm_utils_kill_child (void)
Packit Service b23acc
{
Packit Service b23acc
	GLogLevelFlags fatal_mask;
Packit Service b23acc
	char *argv_watchdog[] = {
Packit Service b23acc
			"bash",
Packit Service b23acc
			"-c",
Packit Service b23acc
			"sleep 4; "
Packit Service b23acc
			"kill -KILL 0; #watchdog for #" TEST_TOKEN,
Packit Service b23acc
			NULL,
Packit Service b23acc
		};
Packit Service b23acc
	char *argv1[] = {
Packit Service b23acc
			"bash",
Packit Service b23acc
			"-c",
Packit Service b23acc
			"trap \"sleep 0.3; exit 10\" EXIT; "
Packit Service b23acc
			"sleep 100000; exit $? #" TEST_TOKEN,
Packit Service b23acc
			NULL,
Packit Service b23acc
		};
Packit Service b23acc
	char *argv2[] = {
Packit Service b23acc
			"bash",
Packit Service b23acc
			"-c",
Packit Service b23acc
			"exit 47; #" TEST_TOKEN,
Packit Service b23acc
			NULL,
Packit Service b23acc
		};
Packit Service b23acc
	char *argv3[] = {
Packit Service b23acc
			"bash",
Packit Service b23acc
			"-c",
Packit Service b23acc
			"trap \"exit 47\" TERM; while true; do :; done; #" TEST_TOKEN,
Packit Service b23acc
			NULL,
Packit Service b23acc
		};
Packit Service b23acc
	char *argv4[] = {
Packit Service b23acc
			"bash",
Packit Service b23acc
			"-c",
Packit Service b23acc
			"trap \"while true; do :; done\" TERM; while true; do :; done; #" TEST_TOKEN,
Packit Service b23acc
			NULL,
Packit Service b23acc
		};
Packit Service b23acc
	pid_t pid1a_1, pid1a_2, pid1a_3, pid2a, pid3a, pid4a;
Packit Service b23acc
	pid_t pid1s_1, pid1s_2, pid1s_3, pid2s, pid3s, pid4s;
Packit Service b23acc
Packit Service b23acc
	const int expected_exit_47 = 12032; /* exit with status 47 */
Packit Service b23acc
	const int expected_signal_TERM = SIGTERM;
Packit Service b23acc
	const int expected_signal_KILL = SIGKILL;
Packit Service b23acc
Packit Service b23acc
	test_nm_utils_kill_child_spawn (argv_watchdog, FALSE);
Packit Service b23acc
Packit Service b23acc
	pid1s_1 = test_nm_utils_kill_child_spawn (argv1, TRUE);
Packit Service b23acc
	pid1s_2 = test_nm_utils_kill_child_spawn (argv1, TRUE);
Packit Service b23acc
	pid1s_3 = test_nm_utils_kill_child_spawn (argv1, TRUE);
Packit Service b23acc
	pid2s = test_nm_utils_kill_child_spawn (argv2, TRUE);
Packit Service b23acc
	pid3s = test_nm_utils_kill_child_spawn (argv3, TRUE);
Packit Service b23acc
	pid4s = test_nm_utils_kill_child_spawn (argv4, TRUE);
Packit Service b23acc
Packit Service b23acc
	pid1a_1 = test_nm_utils_kill_child_spawn (argv1, TRUE);
Packit Service b23acc
	pid1a_2 = test_nm_utils_kill_child_spawn (argv1, TRUE);
Packit Service b23acc
	pid1a_3 = test_nm_utils_kill_child_spawn (argv1, TRUE);
Packit Service b23acc
	pid2a = test_nm_utils_kill_child_spawn (argv2, TRUE);
Packit Service b23acc
	pid3a = test_nm_utils_kill_child_spawn (argv3, TRUE);
Packit Service b23acc
	pid4a = test_nm_utils_kill_child_spawn (argv4, TRUE);
Packit Service b23acc
Packit Service b23acc
	/* give processes time to start (and potentially block signals) ... */
Packit Service b23acc
	g_usleep (G_USEC_PER_SEC / 10);
Packit Service b23acc
Packit Service b23acc
	fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
Packit Service b23acc
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-s-1-1' (*): waiting up to 3000 milliseconds for process to terminate normally after sending SIGTERM (15)...");
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-s-1-1' (*): after sending SIGTERM (15), process * exited by signal 15 (* usec elapsed)");
Packit Service b23acc
	test_nm_utils_kill_child_sync_do ("test-s-1-1", pid1s_1, SIGTERM, 3000, TRUE,  &expected_signal_TERM);
Packit Service b23acc
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-s-1-2' (*): waiting for process to terminate after sending SIGKILL (9)...");
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-s-1-2' (*): after sending SIGKILL (9), process * exited by signal 9 (* usec elapsed)");
Packit Service b23acc
	test_nm_utils_kill_child_sync_do ("test-s-1-2", pid1s_2, SIGKILL, 1000 / 2, TRUE,  &expected_signal_KILL);
Packit Service b23acc
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-s-1-3' (*): waiting up to 1 milliseconds for process to terminate normally after sending no signal (0)...");
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-s-1-3' (*): sending SIGKILL...");
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-s-1-3' (*): after sending no signal (0) and SIGKILL, process * exited by signal 9 (* usec elapsed)");
Packit Service b23acc
	test_nm_utils_kill_child_sync_do ("test-s-1-3", pid1s_3, 0, 1, TRUE,  &expected_signal_KILL);
Packit Service b23acc
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-s-2' (*): process * already terminated normally with status 47");
Packit Service b23acc
	test_nm_utils_kill_child_sync_do ("test-s-2", pid2s, SIGTERM, 3000, TRUE,  &expected_exit_47);
Packit Service b23acc
Packit Service b23acc
	/* send invalid signal. */
Packit Service b23acc
	NMTST_EXPECT_NM_ERROR ("kill child process 'test-s-3-0' (*): failed to send Unexpected signal: Invalid argument (22)");
Packit Service b23acc
	test_nm_utils_kill_child_sync_do ("test-s-3-0", pid3s, -1, 0, FALSE, NULL);
Packit Service b23acc
Packit Service b23acc
	/* really kill pid3s */
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-s-3-1' (*): waiting up to 3000 milliseconds for process to terminate normally after sending SIGTERM (15)...");
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-s-3-1' (*): after sending SIGTERM (15), process * exited normally with status 47 (* usec elapsed)");
Packit Service b23acc
	test_nm_utils_kill_child_sync_do ("test-s-3-1", pid3s, SIGTERM, 3000, TRUE,  &expected_exit_47);
Packit Service b23acc
Packit Service b23acc
	/* pid3s should not be a valid process, hence the call should fail. Note, that there
Packit Service b23acc
	 * is a race here. */
Packit Service b23acc
	NMTST_EXPECT_NM_ERROR ("kill child process 'test-s-3-2' (*): failed due to unexpected return value -1 by waitpid (No child processes, 10) after sending no signal (0)");
Packit Service b23acc
	test_nm_utils_kill_child_sync_do ("test-s-3-2", pid3s, 0, 0, FALSE, NULL);
Packit Service b23acc
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-s-4' (*): waiting up to 1 milliseconds for process to terminate normally after sending SIGTERM (15)...");
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-s-4' (*): sending SIGKILL...");
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-s-4' (*): after sending SIGTERM (15) and SIGKILL, process * exited by signal 9 (* usec elapsed)");
Packit Service b23acc
	test_nm_utils_kill_child_sync_do ("test-s-4", pid4s, SIGTERM, 1, TRUE, &expected_signal_KILL);
Packit Service b23acc
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-a-1-1' (*): wait for process to terminate after sending SIGTERM (15) (send SIGKILL in 3000 milliseconds)...");
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-a-1-1' (*): terminated by signal 15 (* usec elapsed)");
Packit Service b23acc
	test_nm_utils_kill_child_async_do ("test-a-1-1", pid1a_1, SIGTERM, 3000, TRUE, &expected_signal_TERM);
Packit Service b23acc
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-a-1-2' (*): wait for process to terminate after sending SIGKILL (9)...");
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-a-1-2' (*): terminated by signal 9 (* usec elapsed)");
Packit Service b23acc
	test_nm_utils_kill_child_async_do ("test-a-1-2", pid1a_2, SIGKILL, 1000 / 2, TRUE, &expected_signal_KILL);
Packit Service b23acc
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-a-1-3' (*): wait for process to terminate after sending no signal (0) (send SIGKILL in 1 milliseconds)...");
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-a-1-3' (*): process not terminated after * usec. Sending SIGKILL signal");
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-a-1-3' (*): terminated by signal 9 (* usec elapsed)");
Packit Service b23acc
	test_nm_utils_kill_child_async_do ("test-a-1-3", pid1a_3, 0, 1, TRUE, &expected_signal_KILL);
Packit Service b23acc
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-a-2' (*): process * already terminated normally with status 47");
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-a-2' (*): invoke callback: terminated normally with status 47");
Packit Service b23acc
	test_nm_utils_kill_child_async_do ("test-a-2", pid2a, SIGTERM, 3000, TRUE, &expected_exit_47);
Packit Service b23acc
Packit Service b23acc
	NMTST_EXPECT_NM_ERROR ("kill child process 'test-a-3-0' (*): unexpected error sending Unexpected signal: Invalid argument (22)");
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-a-3-0' (*): invoke callback: killing child failed");
Packit Service b23acc
	/* coverity[negative_returns] */
Packit Service b23acc
	test_nm_utils_kill_child_async_do ("test-a-3-0", pid3a, -1, 1000 / 2, FALSE, NULL);
Packit Service b23acc
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-a-3-1' (*): wait for process to terminate after sending SIGTERM (15) (send SIGKILL in 3000 milliseconds)...");
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-a-3-1' (*): terminated normally with status 47 (* usec elapsed)");
Packit Service b23acc
	test_nm_utils_kill_child_async_do ("test-a-3-1", pid3a, SIGTERM, 3000, TRUE, &expected_exit_47);
Packit Service b23acc
Packit Service b23acc
	/* pid3a should not be a valid process, hence the call should fail. Note, that there
Packit Service b23acc
	 * is a race here. */
Packit Service b23acc
	NMTST_EXPECT_NM_ERROR ("kill child process 'test-a-3-2' (*): failed due to unexpected return value -1 by waitpid (No child processes, 10) after sending no signal (0)");
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-a-3-2' (*): invoke callback: killing child failed");
Packit Service b23acc
	test_nm_utils_kill_child_async_do ("test-a-3-2", pid3a, 0, 0, FALSE, NULL);
Packit Service b23acc
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-a-4' (*): wait for process to terminate after sending SIGTERM (15) (send SIGKILL in 1 milliseconds)...");
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-a-4' (*): process not terminated after * usec. Sending SIGKILL signal");
Packit Service b23acc
	NMTST_EXPECT_NM_DEBUG ("kill child process 'test-a-4' (*): terminated by signal 9 (* usec elapsed)");
Packit Service b23acc
	test_nm_utils_kill_child_async_do ("test-a-4", pid4a, SIGTERM, 1, TRUE, &expected_signal_KILL);
Packit Service b23acc
Packit Service b23acc
	g_log_set_always_fatal (fatal_mask);
Packit Service b23acc
Packit Service b23acc
	g_test_assert_expected_messages ();
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
static void
Packit Service b23acc
test_nm_utils_kill_child (void)
Packit Service b23acc
{
Packit Service b23acc
	int err;
Packit Service b23acc
	int exit_status;
Packit Service b23acc
	pid_t gpid;
Packit Service b23acc
	pid_t child_pid;
Packit Service b23acc
Packit Service b23acc
	/* the tests spawns several processes, we want to clean them up
Packit Service b23acc
	 * by sending a SIGKILL to the process group.
Packit Service b23acc
	 *
Packit Service b23acc
	 * The current process might be a session leader, which prevents it from
Packit Service b23acc
	 * creating a new process group. Hence, first fork and let the child
Packit Service b23acc
	 * create a new process group, run the tests, and kill all pending
Packit Service b23acc
	 * processes. */
Packit Service b23acc
	child_pid = fork ();
Packit Service b23acc
	g_assert (child_pid >= 0);
Packit Service b23acc
Packit Service b23acc
	if (child_pid == 0) {
Packit Service b23acc
		gpid = do_test_nm_utils_kill_child_create_and_join_pgroup ();
Packit Service b23acc
Packit Service b23acc
		do_test_nm_utils_kill_child ();
Packit Service b23acc
Packit Service b23acc
		err = setpgid (0, 0);
Packit Service b23acc
		g_assert (err == 0);
Packit Service b23acc
Packit Service b23acc
		kill (-gpid, SIGKILL);
Packit Service b23acc
Packit Service b23acc
		exit (0);
Packit Service b23acc
	};
Packit Service b23acc
Packit Service b23acc
	do {
Packit Service b23acc
		err = waitpid (child_pid, &exit_status, 0);
Packit Service b23acc
	} while (err == -1 && errno == EINTR);
Packit Service b23acc
	g_assert (err == child_pid);
Packit Service b23acc
	if (WIFEXITED (exit_status))
Packit Service b23acc
		g_assert_cmpint (WEXITSTATUS (exit_status), ==, 0);
Packit Service b23acc
	else {
Packit Service b23acc
		g_assert_cmpint (exit_status, ==, 0);
Packit Service b23acc
		g_assert_not_reached ();
Packit Service b23acc
	}
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
/*****************************************************************************/
Packit Service b23acc
Packit Service b23acc
static void
Packit Service b23acc
_remove_at_indexes_init_random_idx (GArray *idx, guint array_len, guint idx_len)
Packit Service b23acc
{
Packit Service b23acc
	GRand *rand = nmtst_get_rand ();
Packit Service b23acc
	gs_free char *mask = NULL;
Packit Service b23acc
	guint i, max_test_idx;
Packit Service b23acc
Packit Service b23acc
	g_assert (idx);
Packit Service b23acc
	g_assert (array_len > 0);
Packit Service b23acc
	g_assert (idx_len >= 1 && idx_len <= array_len);
Packit Service b23acc
Packit Service b23acc
	mask = g_new0 (char, array_len);
Packit Service b23acc
Packit Service b23acc
	max_test_idx = array_len - 1;
Packit Service b23acc
	for (i = 0; i < idx_len; i++) {
Packit Service b23acc
		guint itest;
Packit Service b23acc
Packit Service b23acc
		/* find a index itest that is not yet taken */
Packit Service b23acc
		if (max_test_idx == 0)
Packit Service b23acc
			itest = 0;
Packit Service b23acc
		else
Packit Service b23acc
			itest = g_rand_int_range (rand, 0, max_test_idx);
Packit Service b23acc
		while (itest < array_len && mask[itest])
Packit Service b23acc
			itest++;
Packit Service b23acc
		g_assert (itest <= max_test_idx);
Packit Service b23acc
		g_assert (!mask[itest]);
Packit Service b23acc
Packit Service b23acc
		mask[itest] = TRUE;
Packit Service b23acc
		if (itest == max_test_idx) {
Packit Service b23acc
			g_assert (max_test_idx > 0 || i == idx_len - 1);
Packit Service b23acc
Packit Service b23acc
			if (max_test_idx == 0)
Packit Service b23acc
				g_assert_cmpint (i, ==, idx_len - 1);
Packit Service b23acc
			else {
Packit Service b23acc
				max_test_idx--;
Packit Service b23acc
				while (max_test_idx > 0 && mask[max_test_idx])
Packit Service b23acc
					max_test_idx--;
Packit Service b23acc
				if (mask[max_test_idx])
Packit Service b23acc
					g_assert_cmpint (i, ==, idx_len - 1);
Packit Service b23acc
			}
Packit Service b23acc
		}
Packit Service b23acc
	}
Packit Service b23acc
Packit Service b23acc
	g_array_set_size (idx, 0);
Packit Service b23acc
	for (i = 0; i < array_len; i++) {
Packit Service b23acc
		if (mask[i])
Packit Service b23acc
			g_array_append_val (idx, i);
Packit Service b23acc
	}
Packit Service b23acc
	g_assert_cmpint (idx->len, ==, idx_len);
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
static void
Packit Service b23acc
test_nm_utils_array_remove_at_indexes (void)
Packit Service b23acc
{
Packit Service b23acc
	gs_unref_array GArray *idx = NULL, *array = NULL;
Packit Service b23acc
	gs_unref_hashtable GHashTable *unique = NULL;
Packit Service b23acc
	guint i_len, i_idx_len, i_rnd, i;
Packit Service b23acc
Packit Service b23acc
	idx = g_array_new (FALSE, FALSE, sizeof (guint));
Packit Service b23acc
	array = g_array_new (FALSE, FALSE, sizeof (gssize));
Packit Service b23acc
	unique = g_hash_table_new (nm_direct_hash, NULL);
Packit Service b23acc
	for (i_len = 1; i_len < 20; i_len++) {
Packit Service b23acc
		for (i_idx_len = 1; i_idx_len <= i_len; i_idx_len++) {
Packit Service b23acc
			for (i_rnd = 0; i_rnd < 20; i_rnd++) {
Packit Service b23acc
Packit Service b23acc
				_remove_at_indexes_init_random_idx (idx, i_len, i_idx_len);
Packit Service b23acc
				g_array_set_size (array, i_len);
Packit Service b23acc
				for (i = 0; i < i_len; i++)
Packit Service b23acc
					g_array_index (array, gssize, i) = i;
Packit Service b23acc
Packit Service b23acc
				nm_utils_array_remove_at_indexes (array, &g_array_index (idx, guint, 0), i_idx_len);
Packit Service b23acc
Packit Service b23acc
				g_hash_table_remove_all (unique);
Packit Service b23acc
				/* ensure that all the indexes are still unique */
Packit Service b23acc
				for (i = 0; i < array->len; i++)
Packit Service b23acc
					g_hash_table_add (unique, GUINT_TO_POINTER (g_array_index (array, gssize, i)));
Packit Service b23acc
				g_assert_cmpint (g_hash_table_size (unique), ==, array->len);
Packit Service b23acc
Packit Service b23acc
				for (i = 0; i < idx->len; i++)
Packit Service b23acc
					g_hash_table_add (unique, GUINT_TO_POINTER (g_array_index (idx, guint, i)));
Packit Service b23acc
				g_assert_cmpint (g_hash_table_size (unique), ==, i_len);
Packit Service b23acc
Packit Service b23acc
				/* ensure proper sort order in array */
Packit Service b23acc
				for (i = 0; i < array->len; i++) {
Packit Service b23acc
					gssize i1 = g_array_index (array, gssize, i);
Packit Service b23acc
Packit Service b23acc
					g_assert (i1 >= 0 && i1 < i_len);
Packit Service b23acc
					if (i > 0) {
Packit Service b23acc
						gsize i0 = g_array_index (array, gssize, i - 1);
Packit Service b23acc
						g_assert_cmpint (i0, <, i1);
Packit Service b23acc
					}
Packit Service b23acc
				}
Packit Service b23acc
			}
Packit Service b23acc
		}
Packit Service b23acc
	}
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
/*****************************************************************************/
Packit Service b23acc
Packit Service b23acc
static void
Packit Service b23acc
test_nm_ethernet_address_is_valid (void)
Packit Service b23acc
{
Packit Service b23acc
	g_assert (!nm_ethernet_address_is_valid (NULL, -1));
Packit Service b23acc
	g_assert (!nm_ethernet_address_is_valid (NULL, ETH_ALEN));
Packit Service b23acc
Packit Service b23acc
	g_assert (!nm_ethernet_address_is_valid ("FF:FF:FF:FF:FF:FF", -1));
Packit Service b23acc
	g_assert (!nm_ethernet_address_is_valid ("00:00:00:00:00:00", -1));
Packit Service b23acc
	g_assert (!nm_ethernet_address_is_valid ("44:44:44:44:44:44", -1));
Packit Service b23acc
	g_assert (!nm_ethernet_address_is_valid ("00:30:b4:00:00:00", -1));
Packit Service b23acc
Packit Service b23acc
	g_assert (!nm_ethernet_address_is_valid ("", -1));
Packit Service b23acc
	g_assert (!nm_ethernet_address_is_valid ("1", -1));
Packit Service b23acc
	g_assert (!nm_ethernet_address_is_valid ("2", -1));
Packit Service b23acc
Packit Service b23acc
	g_assert (!nm_ethernet_address_is_valid (((guint8[8]) { 0x00,0x30,0xb4,0x00,0x00,0x00 }), ETH_ALEN));
Packit Service b23acc
	g_assert ( nm_ethernet_address_is_valid (((guint8[8]) { 0x00,0x30,0xb4,0x00,0x00,0x01 }), ETH_ALEN));
Packit Service b23acc
Packit Service b23acc
	/* some Broad cast addresses (with MSB of first octet set). */
Packit Service b23acc
	g_assert (!nm_ethernet_address_is_valid ("57:44:44:44:44:44", -1));
Packit Service b23acc
	g_assert ( nm_ethernet_address_is_valid ("56:44:44:44:44:44", -1));
Packit Service b23acc
	g_assert (!nm_ethernet_address_is_valid (((guint8[8]) { 0x03,0x30,0xb4,0x00,0x00,0x00 }), ETH_ALEN));
Packit Service b23acc
	g_assert ( nm_ethernet_address_is_valid (((guint8[8]) { 0x02,0x30,0xb4,0x00,0x00,0x01 }), ETH_ALEN));
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
/*****************************************************************************/
Packit Service b23acc
Packit Service b23acc
static void
Packit Service b23acc
test_nm_utils_new_vlan_name (void)
Packit Service b23acc
{
Packit Service b23acc
	guint i, j;
Packit Service b23acc
	const char *parent_names[] = {
Packit Service b23acc
		"a",
Packit Service b23acc
		"a2",
Packit Service b23acc
		"a23",
Packit Service b23acc
		"a23456789",
Packit Service b23acc
		"a2345678901",
Packit Service b23acc
		"a23456789012",
Packit Service b23acc
		"a234567890123",
Packit Service b23acc
		"a2345678901234",
Packit Service b23acc
		"a23456789012345",
Packit Service b23acc
		"a234567890123456",
Packit Service b23acc
		"a2345678901234567",
Packit Service b23acc
	};
Packit Service b23acc
Packit Service b23acc
	for (i = 0; i < G_N_ELEMENTS (parent_names); i++) {
Packit Service b23acc
		for (j = 0; j < 10; j++) {
Packit Service b23acc
			gs_free char *ifname = NULL;
Packit Service b23acc
			gs_free char *vlan_id_s = NULL;
Packit Service b23acc
			guint vlan_id;
Packit Service b23acc
Packit Service b23acc
			/* Create a random VLAN id between 0 and 4094 */
Packit Service b23acc
			vlan_id = nmtst_get_rand_uint32 () % 4095;
Packit Service b23acc
Packit Service b23acc
			vlan_id_s = g_strdup_printf (".%d", vlan_id);
Packit Service b23acc
Packit Service b23acc
			ifname = nm_utils_new_vlan_name (parent_names[i], vlan_id);
Packit Service b23acc
			g_assert (ifname && ifname[0]);
Packit Service b23acc
			g_assert_cmpint (strlen (ifname), ==, MIN (15, strlen (parent_names[i]) + strlen (vlan_id_s)));
Packit Service b23acc
			g_assert (g_str_has_suffix (ifname, vlan_id_s));
Packit Service b23acc
			g_assert (ifname[strlen (ifname) - strlen (vlan_id_s)] == '.');
Packit Service b23acc
			g_assert (strncmp (ifname, parent_names[i], strlen (ifname) - strlen (vlan_id_s)) == 0);
Packit Service b23acc
			if (!g_str_has_prefix (ifname, parent_names[i]))
Packit Service b23acc
				g_assert_cmpint (strlen (ifname), ==, 15);
Packit Service b23acc
		}
Packit Service b23acc
	}
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
/*****************************************************************************/
Packit Service b23acc
Packit Service b23acc
NMTST_DEFINE ();
Packit Service b23acc
Packit Service b23acc
int
Packit Service b23acc
main (int argc, char **argv)
Packit Service b23acc
{
Packit Service b23acc
	nmtst_init_assert_logging (&argc, &argv, "DEBUG", "DEFAULT");
Packit Service b23acc
Packit Service b23acc
	g_test_add_func ("/general/nm_utils_monotonic_timestamp_as_boottime", test_nm_utils_monotonic_timestamp_as_boottime);
Packit Service b23acc
	g_test_add_func ("/general/nm_utils_kill_child", test_nm_utils_kill_child);
Packit Service b23acc
	g_test_add_func ("/general/nm_utils_array_remove_at_indexes", test_nm_utils_array_remove_at_indexes);
Packit Service b23acc
	g_test_add_func ("/general/nm_ethernet_address_is_valid", test_nm_ethernet_address_is_valid);
Packit Service b23acc
	g_test_add_func ("/general/nm_utils_new_vlan_name", test_nm_utils_new_vlan_name);
Packit Service b23acc
Packit Service b23acc
	return g_test_run ();
Packit Service b23acc
}