Wireless Daemon for Linux
 help / color / mirror / Atom feed
From: James Prestwood <prestwoj@gmail.com>
To: iwd@lists.01.org
Subject: [PATCH v2 14/15] tools: post test-runner rewrite cleanup
Date: Fri, 28 Aug 2020 09:40:49 -0700	[thread overview]
Message-ID: <20200828164050.1456-15-prestwoj@gmail.com> (raw)
In-Reply-To: <20200828164050.1456-1-prestwoj@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 81167 bytes --]

Removed test-runner.c, and renamed py_runner to test-runner. Removed
tools/test-runner from .gitignore.

This was done as a separate commit to avoid a nasty diff between the
existing test runner, and the new python version
---
 .gitignore                          |    1 -
 Makefile.am                         |    7 -
 tools/{py_runner.py => test-runner} |    0
 tools/test-runner.c                 | 3310 ---------------------------
 4 files changed, 3318 deletions(-)
 rename tools/{py_runner.py => test-runner} (100%)
 delete mode 100644 tools/test-runner.c

diff --git a/.gitignore b/.gitignore
index 93fec4f7..33405af8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,7 +33,6 @@ wired/ead.8
 wired/ead.service
 tools/hwsim
 tools/hwsim.1
-tools/test-runner
 tools/probe-req
 unit/test-cmac-aes
 unit/test-arc4
diff --git a/Makefile.am b/Makefile.am
index e83dbeee..5f16920f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -366,13 +366,6 @@ man_MANS += tools/hwsim.1
 endif
 endif
 
-if TOOLS
-noinst_PROGRAMS += tools/test-runner
-
-tools_test_runner_SOURCES = tools/test-runner.c
-tools_test_runner_LDADD = $(ell_ldadd)
-endif
-
 unit_tests = unit/test-cmac-aes \
 		unit/test-hmac-md5 unit/test-hmac-sha1 unit/test-hmac-sha256 \
 		unit/test-prf-sha1 unit/test-kdf-sha256 \
diff --git a/tools/py_runner.py b/tools/test-runner
similarity index 100%
rename from tools/py_runner.py
rename to tools/test-runner
diff --git a/tools/test-runner.c b/tools/test-runner.c
deleted file mode 100644
index 40148241..00000000
--- a/tools/test-runner.c
+++ /dev/null
@@ -1,3310 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2012-2019  Intel Corporation. All rights reserved.
- *
- *
- *  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.1 of the License, 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, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <string.h>
-#include <getopt.h>
-#include <poll.h>
-#include <dirent.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/mount.h>
-#include <sys/param.h>
-#include <sys/reboot.h>
-#include <sys/time.h>
-#include <glob.h>
-#include <time.h>
-#include <ell/ell.h>
-
-#include "linux/nl80211.h"
-
-#ifndef WAIT_ANY
-#define WAIT_ANY (-1)
-#endif
-
-#define CMDLINE_MAX			2048
-
-#define BIN_IW				"iw"
-#define BIN_HWSIM			"hwsim"
-#define BIN_OFONO			"ofonod"
-#define BIN_PHONESIM			"phonesim"
-#define BIN_HOSTAPD			"hostapd"
-#define BIN_IWD				"iwd"
-
-#define HWSIM_RADIOS_MAX		100
-#define TEST_MAX_EXEC_TIME_SEC		20
-
-static enum action {
-	ACTION_AUTO_TEST,
-	ACTION_UNIT_TEST,
-} test_action;
-
-static const char *own_binary;
-static char **test_argv;
-static int test_argc;
-static char **verbose_apps;
-static char *verbose_opt;
-static bool valgrind;
-static char *gdb_opt;
-static bool enable_debug;
-const char *debug_filter;
-static struct l_settings *hw_config;
-static bool native_hw;
-static bool shell;
-static bool log;
-static char log_dir[PATH_MAX];
-static uid_t log_uid;
-static gid_t log_gid;
-static const char *qemu_binary;
-static const char *kernel_image;
-static const char *exec_home;
-static const char *test_action_params;
-static char top_level_path[PATH_MAX];
-static struct l_queue *wiphy_list;
-
-#if defined(__i386__)
-/*
- * If iwd is being compiled for i386, prefer the i386 qemu but try the
- * X86-64 version as a fallback.
- */
-static const char * const qemu_table[] = {
-	"qemu-system-i386",
-	"/usr/bin/qemu-system-i386",
-	"qemu-system-x86_64",
-	"/usr/bin/qemu-system-x86_64",
-	NULL
-};
-#elif defined(__x86_64__)
-/*
- * If iwd is being built for X86-64 bits there's no point booting a 32-bit
- * only system.
- */
-static const char * const qemu_table[] = {
-	"qemu-system-x86_64",
-	"/usr/bin/qemu-system-x86_64",
-	NULL
-};
-#elif defined(__arm__)
-/*
- * If iwd is being built for ARM look for 32-bit version.
- */
-static const char * const qemu_table[] = {
-	"qemu-system-arm",
-	"/usr/bin/qemu-system-arm",
-	NULL
-};
-#elif defined(__aarch64__)
-/*
- * If iwd is being built for AARCH64 look for 64-bit version.
- */
-static const char * const qemu_table[] = {
-	"qemu-system-aarch64",
-	"/usr/bin/qemu-system-aarch64",
-	NULL
-};
-#elif defined(__powerpc__)
-/*
- * If iwd is being built for PowerPC look for 32-bit version.
- */
-static const char * const qemu_table[] = {
-	"qemu-system-ppc",
-	"/usr/bin/qemu-system-ppc",
-	NULL
-};
-#elif defined(__powerpc64__)
-/*
- * If iwd is being built for PowerPC-64 look for 64-bit version.
- */
-static const char * const qemu_table[] = {
-	"qemu-system-ppc64",
-	"/usr/bin/qemu-system-ppc64",
-	NULL
-};
-#else
-#warning Qemu binary name not defined for this architecture yet
-static const char * const qemu_table[] = { NULL };
-#endif
-
-struct wiphy {
-	char name[20];
-	int id;
-	unsigned int interface_index;
-	bool interface_created : 1;
-	bool used_by_hostapd : 1;
-	char *interface_name;
-	char *hostapd_ctrl_interface;
-	char *hostapd_config;
-	bool can_ap;
-};
-
-static bool check_verbosity(const char *app)
-{
-	char **apps = verbose_apps;
-
-	/*
-	 * All processes are verbose if logging is enabled. Kernel is a bit
-	 * different as we just pipe dmesg into a log file at the end of
-	 * execution.
-	 */
-	if (log && strcmp(app, "kernel") != 0)
-		return true;
-
-	/*
-	 * Turn on output if this is a unit test run. Nothing should output
-	 * anything except the tests themselves and the kernel.
-	 */
-	if (test_action == ACTION_UNIT_TEST && strcmp(app, "kernel") != 0)
-		return true;
-
-	if (!apps)
-		return false;
-
-	while (*apps) {
-		if (!strcmp(app, *apps))
-			return true;
-
-		apps++;
-	}
-
-	return false;
-}
-
-static bool path_exist(const char *path_name)
-{
-	struct stat st;
-
-	if (!stat(path_name, &st))
-		return true;
-
-	return false;
-}
-
-static const char *find_qemu(void)
-{
-	int i;
-
-	for (i = 0; qemu_table[i]; i++)
-		if (path_exist(qemu_table[i]))
-			return qemu_table[i];
-
-	return NULL;
-}
-
-static const char * const kernel_table[] = {
-	"bzImage",
-	"arch/x86/boot/bzImage",
-	"vmlinux",
-	"arch/x86/boot/vmlinux",
-	NULL
-};
-
-static const char *find_kernel(void)
-{
-	int i;
-
-	for (i = 0; kernel_table[i]; i++)
-		if (path_exist(kernel_table[i]))
-			return kernel_table[i];
-
-	return NULL;
-}
-
-static const struct {
-	const char *target;
-	const char *linkpath;
-} dev_table[] = {
-	{ "/proc/self/fd",	"/dev/fd"	},
-	{ "/proc/self/fd/0",	"/dev/stdin"	},
-	{ "/proc/self/fd/1",	"/dev/stdout"	},
-	{ "/proc/self/fd/2",	"/dev/stderr"	},
-	{ }
-};
-
-static const struct {
-	const char *fstype;
-	const char *target;
-	const char *options;
-	unsigned long flags;
-} mount_table[] = {
-	{ "sysfs",    "/sys",     NULL,        MS_NOSUID|MS_NOEXEC|MS_NODEV },
-	{ "proc",     "/proc",    NULL,        MS_NOSUID|MS_NOEXEC|MS_NODEV },
-	{ "devpts",   "/dev/pts", "mode=0620", MS_NOSUID|MS_NOEXEC },
-	{ "tmpfs",    "/dev/shm", "mode=1777",
-					MS_NOSUID|MS_NODEV|MS_STRICTATIME },
-	{ "tmpfs",    "/run",     "mode=0755",
-					MS_NOSUID|MS_NODEV|MS_STRICTATIME },
-	{ "tmpfs",    "/var/lib/iwd", "mode=0755", 0 },
-	{ "tmpfs",    "/tmp",              NULL, 0 },
-	{ "debugfs",  "/sys/kernel/debug", NULL, 0 },
-	{ }
-};
-
-static const char * const config_table[] = {
-	"/usr/share/dbus-1",
-	NULL
-};
-
-static void prepare_sandbox(void)
-{
-	int i;
-
-	for (i = 0; mount_table[i].fstype; i++) {
-		struct stat st;
-
-		if (lstat(mount_table[i].target, &st) < 0) {
-			mkdir(mount_table[i].target, 0755);
-		}
-
-		if (mount(mount_table[i].fstype,
-				mount_table[i].target,
-				mount_table[i].fstype,
-				mount_table[i].flags,
-				mount_table[i].options) < 0) {
-			l_error("Error: Failed to mount filesystem %s",
-							mount_table[i].target);
-		}
-	}
-
-	for (i = 0; dev_table[i].target; i++) {
-
-		if (symlink(dev_table[i].target, dev_table[i].linkpath) < 0)
-			l_error("Failed to create device symlink: %s",
-							strerror(errno));
-	}
-
-	setsid();
-
-	ioctl(STDIN_FILENO, TIOCSCTTY, 1);
-
-	for (i = 0; config_table[i]; i++) {
-		if (mount("tmpfs", config_table[i], "tmpfs",
-				MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME,
-				"mode=0755") < 0)
-			l_error("Failed to create filesystem: %s",
-							strerror(errno));
-	}
-}
-
-static char *const qemu_argv[] = {
-	"",
-	"-machine", "type=q35,accel=kvm:tcg",
-	"-nodefaults",
-	"-no-user-config",
-	"-monitor", "none",
-	"-display", "none",
-	"-m", "192M",
-	"-nographic",
-	"-vga", "none",
-	"-net", "none",
-	"-no-acpi",
-	"-no-hpet",
-	"-no-reboot",
-	"-fsdev", "local,id=fsdev-root,path=/,readonly,security_model=none",
-	"-device", "virtio-9p-pci,fsdev=fsdev-root,mount_tag=/dev/root",
-	"-chardev", "stdio,id=chardev-serial0,signal=off",
-	"-device", "pci-serial,chardev=chardev-serial0",
-	"-device", "virtio-rng-pci",
-	NULL
-};
-
-static char *const qemu_envp[] = {
-	"HOME=/",
-	NULL
-};
-
-static bool check_virtualization(void)
-{
-#if defined(__GNUC__) && (defined(__i386__) || defined(__amd64__))
-	uint32_t ecx;
-
-	__asm__ __volatile__("cpuid" : "=c" (ecx) :
-				"a" (1) : "%ebx", "%edx");
-
-	if (!!(ecx & (1 << 5))) {
-		l_info("Found support for Virtual Machine eXtensions");
-		return true;
-	}
-
-	__asm__ __volatile__("cpuid" : "=c" (ecx) :
-				"a" (0x80000001) : "%ebx", "%edx");
-
-	if (ecx & (1 << 2)) {
-		l_info("Found support for Secure Virtual Machine extension");
-		return true;
-	}
-#endif
-	return false;
-}
-
-static bool start_qemu(void)
-{
-	char cwd[PATH_MAX], testargs[PATH_MAX];
-	char *initcmd, *cmdline;
-	char **argv;
-	int i, pos;
-	bool has_virt;
-	int num_pci = 0, num_usb = 0;
-	char **pci_keys = NULL;
-	char **usb_keys = NULL;
-	L_AUTO_FREE_VAR(char *, log_option) = NULL;
-
-	has_virt = check_virtualization();
-
-	if (!getcwd(cwd, sizeof(cwd)))
-		strcat(cwd, "/");
-
-	if (own_binary[0] == '/')
-		initcmd = l_strdup_printf("%s", own_binary);
-	else
-		initcmd = l_strdup_printf("%s/%s", cwd, own_binary);
-
-	pos = snprintf(testargs, sizeof(testargs), "%s", test_argv[0]);
-
-	for (i = 1; i < test_argc; i++) {
-		int len;
-
-		len = sizeof(testargs) - pos;
-		pos += snprintf(testargs + pos, len, " %s", test_argv[i]);
-	}
-
-	cmdline = l_strdup_printf(
-			"console=ttyS0,115200n8 earlyprintk=serial "
-			"rootfstype=9p "
-			"root=/dev/root "
-			"rootflags=trans=virtio,version=9p2000.u "
-			"acpi=off pci=noacpi noapic %s ro "
-			"mac80211_hwsim.radios=0 init=%s TESTHOME=%s "
-			"TESTVERBOUT=\'%s\' DEBUG_FILTER=\'%s\'"
-			"TEST_ACTION=%u TEST_ACTION_PARAMS=\'%s\' "
-			"TESTARGS=\'%s\' PATH=\'%s\' VALGRIND=%u "
-			"GDB=\'%s\' HW=\'%s\' SHELL=%u "
-			"LOG_PATH=\'%s\' LOG_UID=\'%d\' LOG_GID=\'%d\'",
-			check_verbosity("kernel") ? "ignore_loglevel" : "quiet",
-			initcmd, cwd, verbose_opt ? verbose_opt : "none",
-			enable_debug ? debug_filter : "",
-			test_action,
-			test_action_params ? test_action_params : "",
-			testargs,
-			getenv("PATH"),
-			valgrind,
-			gdb_opt ? gdb_opt : "none",
-			hw_config ? "real" : "virtual",
-			shell,
-			log ? log_dir : "none",
-			log_uid, log_gid);
-
-	if (hw_config) {
-		if (l_settings_has_group(hw_config, "PCIAdapters")) {
-			pci_keys = l_settings_get_keys(hw_config, "PCIAdapters");
-
-			for (num_pci = 0; pci_keys[num_pci]; num_pci++);
-		}
-
-		if (l_settings_has_group(hw_config, "USBAdapters")) {
-			usb_keys = l_settings_get_keys(hw_config, "USBAdapters");
-
-			for (num_usb = 0; usb_keys[num_usb]; num_usb++);
-		}
-
-		if (!pci_keys && !usb_keys) {
-			l_error("hs config had no PCIAdapters or USBAdapters");
-			l_free(initcmd);
-			l_free(cmdline);
-			return false;
-		}
-	}
-
-	/*
-	 * This got quite confusing. We need enough room for:
-	 *
-	 * qemu_argv (static list above with default parameters)
-	 * -kernel,-append,-cpu,-host parameters (7)
-	 * -enable-kvm and/or -usb (2)
-	 * PCI and/or USB parameters (num_pci * 2) (num_usb * 2)
-	 * Logging directory/device (2)
-	 */
-	argv = alloca(sizeof(qemu_argv) + sizeof(char *) *
-				(7 + (2 + (num_pci * 2) + (num_usb * 2) + 2)));
-	memcpy(argv, qemu_argv, sizeof(qemu_argv));
-
-	pos = (sizeof(qemu_argv) / sizeof(char *)) - 1;
-
-	argv[0] = (char *) qemu_binary;
-
-	argv[pos++] = "-kernel";
-	argv[pos++] = (char *) kernel_image;
-	argv[pos++] = "-append";
-	argv[pos++] = (char *) cmdline;
-	argv[pos++] = "-cpu";
-	argv[pos++] = has_virt ? "host" : "max";
-
-	if (pci_keys) {
-		argv[pos++] = "-enable-kvm";
-		for (i = 0; pci_keys[i]; i++) {
-			argv[pos++] = "-device";
-			argv[pos] = alloca(22);
-			sprintf(argv[pos], "vfio-pci,host=%s",
-					l_settings_get_value(hw_config,
-					"PCIAdapters", pci_keys[i]));
-			pos++;
-		}
-	}
-
-	if (usb_keys) {
-		argv[pos++] = "-usb";
-		for (i = 0; usb_keys[i]; i++) {
-			const char *value = l_settings_get_value(hw_config,
-						"USBAdapters", usb_keys[i]);
-			char **info = l_strsplit(value, ',');
-
-			if (l_strv_length(info) != 2) {
-				l_error("hw config formatting error");
-				l_strv_free(info);
-				return false;
-			}
-
-			argv[pos++] = "-device";
-			argv[pos] = alloca(32);
-			sprintf(argv[pos], "usb-host,hostbus=%s,hostaddr=%s",
-						info[0], info[1]);
-			pos++;
-
-			l_strv_free(info);
-		}
-	}
-
-	if (log) {
-		/*
-		 * Create a virtfs device and tag it. This allows the guest to
-		 * mount 'logdir' in the path specified with --log.
-		 */
-		log_option = l_strdup_printf("local,path=%s,mount_tag=logdir,"
-					"security_model=passthrough,id=logdir",
-					log_dir);
-		argv[pos++] = "-virtfs";
-		argv[pos++] = log_option;
-	}
-
-	argv[pos] = NULL;
-
-	execve(argv[0], argv, qemu_envp);
-
-	/* Don't expect to reach here */
-	free(initcmd);
-	free(cmdline);
-
-	return true;
-}
-
-static pid_t execute_program(char *argv[], char *envp[], bool wait,
-				const char *test_name)
-{
-	int status;
-	pid_t pid, child_pid;
-	char *str;
-	bool verbose;
-	char *log_name = argv[0];
-
-	if (!argv[0])
-		return -1;
-
-	/*
-	 * We have a few special cases here:
-	 *
-	 * Since execute_program automatically logs to <process>.log this would
-	 * put all iwd output into valgrind.log rather than iwd.log. Since we
-	 * are explicitly having valgrind output to a log file we can assume any
-	 * output from this is only IWD, and not valgrind.
-	 *
-	 * python3 is special cased so that tests which start IWD manually can
-	 * still show IWD output when using -v iwd.
-	 */
-	if (!strcmp(log_name, "valgrind") || !strcmp(log_name, "python3"))
-		log_name = "iwd";
-
-	str = l_strjoinv(argv, ' ');
-	l_debug("Executing: %s", str);
-	l_free(str);
-
-	child_pid = fork();
-	if (child_pid < 0) {
-		l_error("Failed to fork new process");
-		return -1;
-	}
-
-	if (child_pid == 0) {
-		int fd = -1;
-		L_AUTO_FREE_VAR(char *, log_file) = NULL;
-
-		verbose = check_verbosity(log_name);
-
-		/* No stdout and no logging */
-		if (!verbose && !log)
-			fd = open("/dev/null", O_WRONLY);
-		else if (log && verbose) {
-			/*
-			 * Create the log file for this process. If no test name
-			 * was specified this is a 'global' process (only run
-			 * once, not per-test).
-			 */
-			if (test_name) {
-				log_file = l_strdup_printf("%s/%s/%s.log",
-						log_dir, test_name, log_name);
-			} else
-				log_file = l_strdup_printf("%s/%s.log",
-						log_dir, log_name);
-
-			fd = open(log_file, O_WRONLY | O_CREAT | O_APPEND,
-					S_IRUSR | S_IWUSR);
-			if (fchown(fd, log_uid, log_gid) < 0)
-				l_error("failed to fchown %s", log_file);
-		}
-
-		if (fd > -1) {
-			dup2(fd, 1);
-			dup2(fd, 2);
-
-			close(fd);
-		}
-
-		execvpe(argv[0], argv, envp);
-
-		l_error("Failed to call execvpe for: %s. Error: %s", argv[0],
-							strerror(errno));
-
-		exit(EXIT_FAILURE);
-	}
-
-	if (!wait)
-		goto exit;
-
-	do {
-		pid = waitpid(child_pid, &status, 0);
-	} while (!WIFEXITED(status) && pid == child_pid);
-
-	if (WEXITSTATUS(status) != EXIT_SUCCESS)
-		return -1;
-
-exit:
-	return child_pid;
-}
-
-static void kill_process(pid_t pid)
-{
-	int status;
-	int i = 0;
-
-	l_debug("Terminate pid: %d", pid);
-
-	kill(pid, SIGTERM);
-
-	do {
-		if (waitpid(pid, &status, WNOHANG) == pid)
-			return;
-
-		usleep(100000);
-	} while (!WIFEXITED(status) && !WIFSIGNALED(status) && i++ < 20);
-
-	l_error("Failed to kill process %d gracefully", pid);
-	kill(pid, SIGKILL);
-
-	/* SIGKILL shouldn't need WNOHANG */
-	waitpid(pid, &status, 0);
-}
-
-static bool wait_for_socket(const char *socket, useconds_t wait_time)
-{
-	int i = 0;
-
-	do {
-		if (path_exist(socket))
-			return true;
-
-		usleep(wait_time);
-	} while ((wait_time > 0) ? i++ < 20 : true);
-
-	l_error("Error: cannot find socket: %s", socket);
-	return false;
-}
-
-static void create_dbus_system_conf(void)
-{
-	FILE *fp;
-
-	fp = fopen("/usr/share/dbus-1/system.conf", "we");
-	if (!fp)
-		return;
-
-	fputs("<!DOCTYPE busconfig PUBLIC ", fp);
-	fputs("\"-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN\" ", fp);
-	fputs("\"http://www.freedesktop.org/standards/dbus/1.0/", fp);
-	fputs("busconfig.dtd\">\n", fp);
-	fputs("<busconfig>\n", fp);
-	fputs("<type>system</type>\n", fp);
-	fputs("<listen>unix:path=/run/dbus/system_bus_socket</listen>\n", fp);
-	fputs("<limit name=\"reply_timeout\">2147483647</limit>", fp);
-	fputs("<auth>ANONYMOUS</auth>\n", fp);
-	fputs("<allow_anonymous/>\n", fp);
-	fputs("<policy context=\"default\">\n", fp);
-	fputs("<allow user=\"*\"/>\n", fp);
-	fputs("<allow own=\"*\"/>\n", fp);
-	fputs("<allow send_type=\"method_call\"/>\n", fp);
-	fputs("<allow send_type=\"signal\"/>\n", fp);
-	fputs("<allow send_type=\"method_return\"/>\n", fp);
-	fputs("<allow send_type=\"error\"/>\n", fp);
-	fputs("<allow receive_type=\"method_call\"/>\n", fp);
-	fputs("<allow receive_type=\"signal\"/>\n", fp);
-	fputs("<allow receive_type=\"method_return\"/>\n", fp);
-	fputs("<allow receive_type=\"error\"/>\n", fp);
-	fputs("</policy>\n", fp);
-	fputs("</busconfig>\n", fp);
-
-	fclose(fp);
-
-	mkdir("/run/dbus", 0755);
-}
-
-static bool start_dbus_daemon(void)
-{
-	char *argv[4];
-	pid_t pid;
-
-	argv[0] = "dbus-daemon";
-	argv[1] = "--system";
-	argv[2] = "--nosyslog";
-	argv[3] = NULL;
-
-	if (check_verbosity("dbus"))
-		setenv("DBUS_VERBOSE", "1", true);
-
-	pid = execute_program(argv, environ, false, NULL);
-	if (pid < 0)
-		return false;
-
-	if (!wait_for_socket("/run/dbus/system_bus_socket", 25 * 10000))
-		return false;
-
-	if (check_verbosity("dbus-monitor")) {
-		argv[0] = "dbus-monitor";
-		argv[1] = "--system";
-		argv[2] = NULL;
-		execute_program(argv, environ, false, NULL);
-	}
-
-	l_debug("D-Bus is running");
-
-	return true;
-}
-
-static bool start_haveged(void)
-{
-	char *argv[2];
-	pid_t pid;
-
-	argv[0] = "haveged";
-	argv[1] = NULL;
-
-	pid = execute_program(argv, environ, true, NULL);
-	if (pid < 0)
-		return false;
-
-	return true;
-}
-
-static bool set_interface_state(const char *if_name, bool isUp)
-{
-	char *state, *argv[4];
-	pid_t pid;
-
-	if (isUp)
-		state = "up";
-	else
-		state = "down";
-
-	argv[0] = "ifconfig";
-	argv[1] = (char *) if_name;
-	argv[2] = state;
-	argv[3] = NULL;
-
-	pid = execute_program(argv, environ, true, NULL);
-	if (pid < 0)
-		return false;
-
-	return true;
-}
-
-static bool create_interface(const char *if_name, const char *phy_name)
-{
-	char *argv[9];
-	pid_t pid;
-
-	argv[0] = BIN_IW;
-	argv[1] = "phy";
-	argv[2] = (char *) phy_name;
-	argv[3] = "interface";
-	argv[4] = "add";
-	argv[5] = (char *) if_name;
-	argv[6] = "type";
-	argv[7] = "managed";
-	argv[8] = NULL;
-
-	pid = execute_program(argv, environ, true, NULL);
-	if (pid < 0)
-		return false;
-
-	return true;
-}
-
-static bool delete_interface(const char *if_name)
-{
-	char *argv[5];
-	pid_t pid;
-
-	argv[0] = BIN_IW;
-	argv[1] = "dev";
-	argv[2] = (char *) if_name;
-	argv[3] = "del";
-	argv[4] = NULL;
-
-	pid = execute_program(argv, environ, true, NULL);
-	if (pid < 0)
-		return false;
-
-	return true;
-}
-
-static bool list_interfaces(void)
-{
-	char *argv[3];
-	pid_t pid;
-
-	argv[0] = "ifconfig";
-	argv[1] = "-a";
-	argv[2] = NULL;
-
-	pid = execute_program(argv, environ, true, NULL);
-	if (pid < 0)
-		return false;
-
-	return true;
-}
-
-static bool list_hwsim_radios(void)
-{
-	char *argv[3];
-	pid_t pid;
-
-	argv[0] = BIN_HWSIM;
-	argv[1] = "--list";
-	argv[2] = NULL;
-
-	pid = execute_program(argv, environ, true, NULL);
-	if (pid < 0)
-		return false;
-
-	return true;
-}
-
-static int read_radio_id(void)
-{
-	static int current_radio_id;
-
-	return current_radio_id++;
-}
-
-struct hwsim_radio_params {
-	unsigned int channels;
-	bool p2p_device;
-	bool use_chanctx;
-	char *iftype_disable;
-	char *cipher_disable;
-};
-
-static int create_hwsim_radio(const char *radio_name,
-				struct hwsim_radio_params *params)
-{
-	char *argv[10];
-	pid_t pid;
-	int idx = 0;
-
-	/*TODO add the rest of params*/
-	argv[idx++] = BIN_HWSIM;
-	argv[idx++] = "--create";
-	argv[idx++] = "--name";
-	argv[idx++] = (char *) radio_name;
-	argv[idx++] = "--nointerface";
-
-	if (params->iftype_disable) {
-		argv[idx++] = "--iftype-disable";
-		argv[idx++] = params->iftype_disable;
-	}
-
-	if (params->cipher_disable) {
-		argv[idx++] = "--cipher-disable";
-		argv[idx++] = params->cipher_disable;
-	}
-
-	argv[idx] = NULL;
-
-	pid = execute_program(argv, environ, true, NULL);
-	if (pid < 0)
-		return -1;
-
-	return read_radio_id();
-}
-
-static bool destroy_hwsim_radio(int radio_id)
-{
-	char *argv[4];
-	char destroy_param[20];
-	pid_t pid;
-
-	sprintf(destroy_param, "--destroy=%d", radio_id);
-
-	argv[0] = BIN_HWSIM;
-	argv[1] = destroy_param;
-	argv[2] = NULL;
-
-	pid = execute_program(argv, environ, true, NULL);
-	if (pid < 0)
-		return false;
-
-	return true;
-}
-
-static pid_t register_hwsim_as_trans_medium(void)
-{
-	char *argv[16];
-	unsigned int idx = 0;
-
-	if (strcmp(gdb_opt, "hwsim") == 0) {
-		argv[idx++] = "gdb";
-		argv[idx++] = "--args";
-	}
-
-	argv[idx++] = BIN_HWSIM;
-	argv[idx++] = NULL;
-
-	return execute_program(argv, environ, false, NULL);
-}
-
-static void terminate_medium(pid_t medium_pid)
-{
-	kill_process(medium_pid);
-}
-
-#define HOSTAPD_CTRL_INTERFACE_PREFIX "/var/run/hostapd"
-
-static bool loopback_started;
-
-static void start_loopback(void)
-{
-	char *argv[7];
-
-	if (loopback_started)
-		return;
-
-	argv[0] = "ifconfig";
-	argv[1] = "lo";
-	argv[2] = "127.0.0.1";
-	argv[3] = "up";
-	argv[4] = NULL;
-	execute_program(argv, environ, false, NULL);
-
-	argv[0] = "route";
-	argv[1] = "add";
-	argv[2] = "127.0.0.1";
-	argv[3] = NULL;
-	execute_program(argv, environ, false, NULL);
-
-	loopback_started = true;
-}
-
-static pid_t start_phonesim(const char *test_name)
-{
-	char *argv[5];
-
-	argv[0] = BIN_PHONESIM;
-	argv[1] = "-p";
-	argv[2] = "12345";
-	argv[3] = "/usr/share/phonesim/default.xml";
-	argv[4] = NULL;
-
-	start_loopback();
-
-	setenv("OFONO_PHONESIM_CONFIG", "/tmp/phonesim.conf", true);
-
-	return execute_program(argv, environ, false, test_name);
-}
-
-static void stop_phonesim(pid_t pid)
-{
-	kill_process(pid);
-}
-
-static pid_t start_ofono(const char *test_name)
-{
-	char *argv[5];
-	bool verbose = check_verbosity(BIN_OFONO);
-
-	argv[0] = BIN_OFONO;
-	argv[1] = "-n";
-	argv[2] = "--plugin=atmodem,phonesim";
-
-	if (verbose)
-		argv[3] = "-d";
-	else
-		argv[3] = NULL;
-
-	argv[4] = NULL;
-
-	start_loopback();
-
-	return execute_program(argv, environ, false, test_name);
-}
-
-static void stop_ofono(pid_t pid)
-{
-	kill_process(pid);
-}
-
-static pid_t start_hostapd(char **config_files, struct wiphy **wiphys,
-				const char *test_name, const char *radius_conf)
-{
-	char **argv;
-	pid_t pid;
-	int idx = 0;
-	uint32_t wait = 25 * 10000;
-	bool verbose = check_verbosity(BIN_HOSTAPD);
-	size_t ifnames_size;
-	char *ifnames;
-	int i;
-
-	for (i = 0, ifnames_size = 0; wiphys[i]; i++)
-		ifnames_size += 1 + strlen(wiphys[i]->interface_name);
-
-	argv = alloca(sizeof(char *) * (9 + i));
-
-	if (strcmp(gdb_opt, "hostapd") == 0) {
-		argv[idx++] = "gdb";
-		argv[idx++] = "--args";
-		wait = 0;
-	}
-
-	argv[idx++] = BIN_HOSTAPD;
-
-	ifnames = alloca(ifnames_size);
-	argv[idx++] = "-i";
-	argv[idx++] = ifnames;
-
-	argv[idx++] = "-g";
-	argv[idx++] = wiphys[0]->hostapd_ctrl_interface;
-
-	for (i = 0, ifnames_size = 0; wiphys[i]; i++) {
-		if (ifnames_size)
-			ifnames[ifnames_size++] = ',';
-		strcpy(ifnames + ifnames_size, wiphys[i]->interface_name);
-		ifnames_size += strlen(wiphys[i]->interface_name);
-
-		argv[idx++] = config_files[i];
-	}
-
-	if (radius_conf)
-		argv[idx++] = (void *)radius_conf;
-
-	if (verbose) {
-		argv[idx++] = "-d";
-		argv[idx++] = NULL;
-	} else {
-		argv[idx++] = NULL;
-	}
-
-	pid = execute_program(argv, environ, false, log ? test_name : NULL);
-	if (pid < 0) {
-		goto exit;
-	}
-
-	if (!wait_for_socket(wiphys[0]->hostapd_ctrl_interface, wait))
-		pid = -1;
-exit:
-	return pid;
-}
-
-static void destroy_hostapd_instances(pid_t hostapd_pids[])
-{
-	int i = 0;
-
-	while (hostapd_pids[i] != -1) {
-		kill_process(hostapd_pids[i]);
-
-		l_debug("hostapd instance with pid=%d is destroyed",
-			hostapd_pids[i]);
-
-		hostapd_pids[i] = -1;
-
-		i++;
-	}
-}
-
-#define TEST_TOP_DIR_DEFAULT_NAME	"autotests"
-#define TEST_DIR_PREFIX			"test"
-
-static bool is_test_file(const char *file)
-{
-	size_t i;
-	static const char * const test_file_extension_table[] = {
-		"test",
-		"test.py",
-		"Test",
-		"Test.py",
-		NULL
-	};
-
-	for (i = 0; test_file_extension_table[i]; i++) {
-		if (l_str_has_suffix(file, test_file_extension_table[i]))
-			return true;
-	}
-
-	return false;
-}
-
-static int is_test_dir(const char *dir)
-{
-	return strncmp(dir, TEST_DIR_PREFIX, strlen(TEST_DIR_PREFIX)) == 0;
-}
-
-static bool find_test_configuration(const char *path, int level,
-						struct l_queue *config_queue);
-
-struct test_entry {
-	struct l_queue *test_queue;
-	char *path;
-};
-
-static int insert_py_test(const void *a, const void *b, void *user_data)
-{
-	return strcmp((const char *)a, (const char *)b);
-}
-
-static int insert_test_entry(const void *a, const void *b, void *user_data)
-{
-	const struct test_entry *entry_a = a;
-	const struct test_entry *entry_b = b;
-
-	return strcmp(entry_a->path, entry_b->path);
-}
-
-static bool add_path(const char *path, int level, struct l_queue *config_queue)
-{
-	DIR *dir = NULL;
-	struct l_queue *py_test_queue = NULL;
-	struct dirent *entry;
-	char *npath;
-
-	dir = opendir(path);
-	if (!dir) {
-		l_error("Test directory does not exist: %s", path);
-		return false;
-	}
-
-	while ((entry = readdir(dir))) {
-		if (entry->d_type == DT_DIR) {
-			if (!strcmp(entry->d_name, ".") ||
-					!strcmp(entry->d_name, ".."))
-				continue;
-
-			if (level == 0 && is_test_dir(entry->d_name)) {
-				npath = l_strdup_printf("%s/%s", path,
-								entry->d_name);
-
-				find_test_configuration(npath, 1, config_queue);
-
-				l_free(npath);
-			}
-		} else if (level == 1 && is_test_file(entry->d_name)) {
-			if (!py_test_queue)
-				py_test_queue = l_queue_new();
-
-			l_queue_insert(py_test_queue, l_strdup(entry->d_name),
-						insert_py_test, NULL);
-		}
-	}
-
-	if (py_test_queue && !l_queue_isempty(py_test_queue)) {
-		struct test_entry *entry = l_new(struct test_entry, 1);
-
-		entry->test_queue = py_test_queue;
-		entry->path = l_strdup(path);
-
-		l_queue_insert(config_queue, entry, insert_test_entry, NULL);
-	}
-
-	closedir(dir);
-	return true;
-}
-
-static bool find_test_configuration(const char *path, int level,
-						struct l_queue *config_queue)
-{
-	glob_t glist;
-	int i = 0;
-	int ret;
-
-	if (!config_queue)
-		return false;
-
-	ret = glob(path, 0, NULL, &glist);
-	if (ret != 0) {
-		l_error("Could not match glob %s", path);
-		return false;
-	}
-
-	while (glist.gl_pathv[i]) {
-		if (!add_path(glist.gl_pathv[i], level, config_queue))
-			return false;
-
-		i++;
-	}
-
-	return true;
-}
-
-#define HW_CONFIG_FILE_NAME		"hw.conf"
-#define HW_CONFIG_GROUP_HOSTAPD		"HOSTAPD"
-#define HW_CONFIG_GROUP_SETUP		"SETUP"
-
-#define HW_CONFIG_SETUP_NUM_RADIOS	"num_radios"
-#define HW_CONFIG_SETUP_RADIO_CONFS	"radio_confs"
-#define HW_CONFIG_SETUP_MAX_EXEC_SEC	"max_test_exec_interval_sec"
-#define HW_CONFIG_SETUP_TMPFS_EXTRAS	"tmpfs_extra_stuff"
-#define HW_CONFIG_SETUP_START_IWD	"start_iwd"
-#define HW_CONFIG_SETUP_IWD_CONF_DIR	"iwd_config_dir"
-#define HW_CONFIG_SETUP_REG_DOMAIN	"reg_domain"
-#define HW_CONFIG_SETUP_NEEDS_HWSIM	"needs_hwsim"
-
-static struct l_settings *read_hw_config(const char *test_dir_path)
-{
-	struct l_settings *hw_settings;
-	char *hw_file;
-
-	hw_file = l_strdup_printf("%s/%s", test_dir_path, HW_CONFIG_FILE_NAME);
-
-	hw_settings = l_settings_new();
-
-	if (!l_settings_load_from_file(hw_settings, hw_file)) {
-		l_error("No %s file found", HW_CONFIG_FILE_NAME);
-		goto error_exit;
-	}
-
-	if (!l_settings_has_group(hw_settings, HW_CONFIG_GROUP_SETUP)) {
-		l_error("No %s setting group found in %s",
-						HW_CONFIG_GROUP_SETUP, hw_file);
-		goto error_exit;
-	}
-
-	l_free(hw_file);
-	return hw_settings;
-
-error_exit:
-	l_free(hw_file);
-	l_settings_free(hw_settings);
-	return NULL;
-}
-
-#define HW_CONFIG_PHY_CHANNELS	"channels"
-#define HW_CONFIG_PHY_CHANCTX	"use_chanctx"
-#define HW_CONFIG_PHY_P2P	"p2p_device"
-#define HW_CONFIG_PHY_IFTYPE_DISABLE "iftype_disable"
-#define HW_CONFIG_PHY_CIPHER_DISABLE "cipher_disable"
-
-#define HW_MIN_NUM_RADIOS	1
-
-#define HW_INTERFACE_PREFIX	"wln"
-#define HW_INTERFACE_STATE_UP   true
-#define HW_INTERFACE_STATE_DOWN false
-
-static bool configure_hw_radios(struct l_settings *hw_settings,
-						struct l_queue *wiphy_list)
-{
-	char **radio_conf_list;
-	int i, num_radios_requested;
-	bool status = false;
-
-	l_settings_get_int(hw_settings, HW_CONFIG_GROUP_SETUP,
-						HW_CONFIG_SETUP_NUM_RADIOS,
-							&num_radios_requested);
-
-	if (num_radios_requested < HW_MIN_NUM_RADIOS) {
-		l_error("%s must be greater or equal to %d",
-			HW_CONFIG_SETUP_NUM_RADIOS, HW_MIN_NUM_RADIOS);
-		return false;
-	}
-
-	radio_conf_list =
-		l_settings_get_string_list(hw_settings, HW_CONFIG_GROUP_SETUP,
-						HW_CONFIG_SETUP_RADIO_CONFS,
-									':');
-	for (i = 0; i < num_radios_requested; i++) {
-		struct wiphy *wiphy;
-		struct hwsim_radio_params params = { 0 };
-
-		wiphy = l_new(struct wiphy, 1);
-
-		sprintf(wiphy->name, "rad%d", i);
-
-		/* radio not in radio_confs, use default parameters */
-		if (!l_strv_contains(radio_conf_list, wiphy->name)) {
-			params.channels = 1;
-			params.p2p_device = true;
-			params.use_chanctx = true;
-			goto create;
-		}
-
-		if (!l_settings_get_uint(hw_settings, wiphy->name,
-					HW_CONFIG_PHY_CHANNELS,
-					&params.channels))
-			params.channels = 1;
-
-		if (!l_settings_get_bool(hw_settings, wiphy->name,
-					HW_CONFIG_PHY_P2P, &params.p2p_device))
-			params.p2p_device = true;
-
-		if (!l_settings_get_bool(hw_settings, wiphy->name,
-					HW_CONFIG_PHY_CHANCTX,
-					&params.use_chanctx))
-			params.use_chanctx = true;
-
-		params.iftype_disable = l_settings_get_string(hw_settings,
-					wiphy->name,
-					HW_CONFIG_PHY_IFTYPE_DISABLE);
-		params.cipher_disable = l_settings_get_string(hw_settings,
-					wiphy->name,
-					HW_CONFIG_PHY_CIPHER_DISABLE);
-
-create:
-		wiphy->id = create_hwsim_radio(wiphy->name, &params);
-		wiphy->can_ap = true;
-
-		if (wiphy->id < 0) {
-			l_free(wiphy);
-			goto exit;
-		}
-
-		l_queue_push_tail(wiphy_list, wiphy);
-	}
-
-	status = true;
-
-exit:
-	l_strfreev(radio_conf_list);
-	return status;
-}
-
-static void wiphy_free(void *data)
-{
-	struct wiphy *wiphy = data;
-
-	if (wiphy->interface_created) {
-		set_interface_state(wiphy->interface_name,
-					HW_INTERFACE_STATE_DOWN);
-
-		if (delete_interface(wiphy->interface_name))
-			l_debug("Removed interface %s", wiphy->interface_name);
-		else
-			l_error("Failed to remove interface %s",
-				wiphy->interface_name);
-	}
-
-	/* Native interfaces cannot be destroyed */
-	if (native_hw) {
-		set_interface_state(wiphy->interface_name,
-					HW_INTERFACE_STATE_DOWN);
-	} else {
-		destroy_hwsim_radio(wiphy->id);
-		l_debug("Removed radio id %d", wiphy->id);
-	}
-
-	l_free(wiphy->hostapd_config);
-	l_free(wiphy->hostapd_ctrl_interface);
-	l_free(wiphy->interface_name);
-
-	l_free(wiphy);
-}
-
-static bool configure_hostapd_instances(struct l_settings *hw_settings,
-						char *config_dir_path,
-						struct l_queue *wiphy_list,
-						pid_t hostapd_pids_out[],
-						int *phys_used)
-{
-	char **hostap_keys;
-	int i;
-	char **hostapd_config_file_paths;
-	struct wiphy **wiphys;
-	const char *radius_config = NULL;
-
-	*phys_used = 0;
-
-	if (!l_settings_has_group(hw_settings, HW_CONFIG_GROUP_HOSTAPD)) {
-		l_info("No hostapd instances to create");
-		return true;
-	}
-
-	hostap_keys =
-		l_settings_get_keys(hw_settings, HW_CONFIG_GROUP_HOSTAPD);
-
-	for (i = 0; hostap_keys[i]; i++);
-
-	hostapd_config_file_paths = l_new(char *, i + 1);
-	wiphys = alloca(sizeof(struct wiphy *) * (i + 1));
-	memset(wiphys, 0, sizeof(struct wiphy *) * (i + 1));
-
-	hostapd_pids_out[0] = -1;
-
-	for (i = 0; hostap_keys[i]; i++) {
-		const struct l_queue_entry *wiphy_entry;
-		const char *hostapd_config_file;
-		unsigned wiphy_idx = 0;
-
-		hostapd_config_file =
-			l_settings_get_value(hw_settings,
-						HW_CONFIG_GROUP_HOSTAPD,
-						hostap_keys[i]);
-
-		hostapd_config_file_paths[i] =
-			l_strdup_printf("%s/%s", config_dir_path,
-					hostapd_config_file);
-
-		if (!path_exist(hostapd_config_file_paths[i])) {
-			l_error("%s : hostapd configuration file [%s] "
-				"does not exist.", HW_CONFIG_FILE_NAME,
-						hostapd_config_file_paths[i]);
-			goto done;
-		}
-
-		if (!strcmp(hostap_keys[i], "radius_server")) {
-			radius_config = l_settings_get_value(hw_settings,
-						HW_CONFIG_GROUP_HOSTAPD,
-						"radius_server");
-			continue;
-		}
-
-		for (wiphy_entry = l_queue_get_entries(wiphy_list);
-					wiphy_entry;
-					wiphy_entry = wiphy_entry->next,
-					wiphy_idx++) {
-			struct wiphy *wiphy = wiphy_entry->data;
-
-			/*
-			 * We can skip this check in native mode since we have
-			 * no control over the phy name. Any test requiring a
-			 * "special" radio should not be ran in native mode.
-			 */
-			if (!native_hw && strcmp(wiphy->name, hostap_keys[i]))
-				continue;
-
-			if (wiphy->used_by_hostapd) {
-				/*
-				 * Since we bypass the above check in native
-				 * mode we could still get here. We can just
-				 * continue searching for more adapters if this
-				 * one is already in use.
-				 */
-				if (native_hw)
-					continue;
-
-				l_error("Wiphy %s already used by hostapd",
-					wiphy->name);
-				goto done;
-			}
-
-			if (!wiphy->can_ap)
-				continue;
-
-			wiphys[i] = wiphy;
-			break;
-		}
-
-		if (!wiphy_entry) {
-			l_error("Failed to find available wiphy.");
-			goto done;
-		}
-
-		if (native_hw)
-			goto hostapd_done;
-
-		wiphys[i]->interface_name = l_strdup_printf("%s%d",
-							HW_INTERFACE_PREFIX,
-							wiphy_idx);
-		if (!create_interface(wiphys[i]->interface_name,
-					wiphys[i]->name)) {
-			l_error("Failed to create hostapd interface %s on "
-				"radio %s",
-				wiphys[i]->interface_name, wiphys[i]->name);
-			goto done;
-		}
-
-		wiphys[i]->interface_created = true;
-		l_info("Created hostapd interface %s on %s radio",
-			wiphys[i]->interface_name, wiphys[i]->name);
-
-		if (!native_hw && !set_interface_state(wiphys[i]->interface_name,
-						HW_INTERFACE_STATE_UP)) {
-			l_error("Failed to set %s state UP",
-				wiphys[i]->interface_name);
-			goto done;
-		}
-
-hostapd_done:
-		wiphys[i]->used_by_hostapd = true;
-		wiphys[i]->hostapd_ctrl_interface =
-			l_strdup_printf("%s/%s", HOSTAPD_CTRL_INTERFACE_PREFIX,
-					wiphys[0]->interface_name);
-		wiphys[i]->hostapd_config = l_strdup(hostapd_config_file);
-
-		(*phys_used)++;
-	}
-
-	hostapd_pids_out[0] = start_hostapd(hostapd_config_file_paths, wiphys,
-						basename(config_dir_path),
-						radius_config);
-	hostapd_pids_out[1] = -1;
-
-done:
-	l_strfreev(hostapd_config_file_paths);
-
-	if (hostapd_pids_out[0] < 1)
-		return false;
-
-	return true;
-}
-
-static pid_t start_iwd(const char *config_dir, struct l_queue *wiphy_list,
-		const char *ext_options, int num_phys, const char *test_name)
-{
-	char *argv[13], **envp;
-	char *iwd_phys = NULL;
-	pid_t ret;
-	int idx = 0;
-	L_AUTO_FREE_VAR(char *, fd_option) = NULL;
-
-	if (valgrind) {
-		L_AUTO_FREE_VAR(char *, valgrind_log);
-		int fd;
-
-		argv[idx++] = "valgrind";
-		argv[idx++] = "--leak-check=full";
-
-		/*
-		 * Valgrind needs --log-fd if we want both stderr and stdout
-		 */
-		if (log)
-			valgrind_log = l_strdup_printf("%s/%s/valgrind.log",
-							log_dir, test_name);
-		else
-			valgrind_log = l_strdup("/tmp/valgrind.log");
-
-		fd = open(valgrind_log, O_WRONLY | O_CREAT | O_APPEND,
-					S_IRUSR | S_IWUSR);
-
-		if (log) {
-			if (fchown(fd, log_uid, log_gid) < 0)
-				l_error("chown failed");
-		}
-
-		fd_option = l_strdup_printf("--log-fd=%d", fd);
-		argv[idx++] = fd_option;
-	}
-
-	if (strcmp(gdb_opt, "iwd") == 0) {
-		argv[idx++] = "gdb";
-		argv[idx++] = "--args";
-	}
-
-	argv[idx++] = BIN_IWD;
-
-	if (check_verbosity(BIN_IWD) || shell)
-		argv[idx++] = "-d";
-
-	argv[idx] = NULL;
-
-	if (wiphy_list) {
-		const struct l_queue_entry *wiphy_entry;
-		struct l_string *list = l_string_new(64);
-
-		for (wiphy_entry = l_queue_get_entries(wiphy_list);
-					wiphy_entry;
-					wiphy_entry = wiphy_entry->next) {
-			struct wiphy *wiphy = wiphy_entry->data;
-
-			if (wiphy->used_by_hostapd)
-				continue;
-
-			/*
-			 * Break out, only adding the required number of phys
-			 * for this test.
-			 */
-			if (num_phys == 0)
-				break;
-
-			l_string_append_printf(list, "%s,", wiphy->name);
-
-			num_phys--;
-		}
-
-		iwd_phys = l_string_unwrap(list);
-		/* Take care of last comma */
-		iwd_phys[strlen(iwd_phys) - 1] = '\0';
-
-		argv[idx++] = "-p";
-		argv[idx++] = iwd_phys;
-		argv[idx] = NULL;
-	}
-
-	argv[idx++] = (char *)ext_options;
-	argv[idx] = NULL;
-
-	envp = l_strv_copy(environ);
-	envp = l_strv_append_printf(envp, "CONFIGURATION_DIRECTORY=%s",
-							config_dir);
-	envp = l_strv_append_printf(envp, "STATE_DIRECTORY=%s",
-							DAEMON_STORAGEDIR);
-
-	ret = execute_program(argv, envp, false, test_name);
-
-	l_strv_free(envp);
-
-	l_free(iwd_phys);
-
-	return ret;
-}
-
-static void terminate_iwd(pid_t iwd_pid)
-{
-	kill_process(iwd_pid);
-}
-
-static pid_t start_monitor(const char *test_name)
-{
-	char *argv[6];
-	char *write_arg;
-	pid_t pid;
-
-	write_arg = l_strdup_printf("%s/%s/monitor.pcap", log_dir, test_name);
-
-	argv[0] = "iwmon";
-	argv[1] = "--nortnl";
-	argv[2] = "--nowiphy";
-	argv[3] = "--write";
-	argv[4] = write_arg;
-	argv[5] = NULL;
-
-	pid = execute_program(argv, environ, false, test_name);
-
-	l_free(write_arg);
-
-	return pid;
-}
-
-static bool create_tmpfs_extra_stuff(char **tmpfs_extra_stuff)
-{
-	size_t i = 0;
-
-	if (!tmpfs_extra_stuff)
-		return true;
-
-	while (tmpfs_extra_stuff[i]) {
-		char *link_dir;
-		char *target_dir;
-
-		target_dir = realpath(tmpfs_extra_stuff[i], NULL);
-
-		if (!path_exist(target_dir)) {
-			l_error("No such directory: %s", target_dir);
-			l_free(target_dir);
-			return false;
-		}
-
-		link_dir = l_strdup_printf("%s%s", "/tmp",
-						rindex(target_dir, '/'));
-
-		if (symlink(target_dir, link_dir) < 0) {
-			l_error("Failed to create symlink %s for %s: %s",
-					link_dir, target_dir, strerror(errno));
-
-			l_free(target_dir);
-			l_free(link_dir);
-			return false;
-		}
-
-		l_free(tmpfs_extra_stuff[i]);
-		l_free(target_dir);
-
-		tmpfs_extra_stuff[i] = link_dir;
-		i++;
-	}
-
-	return true;
-}
-
-static bool remove_absolute_path_dirs(char **tmpfs_extra_stuff)
-{
-	size_t i = 0;
-
-	if (!tmpfs_extra_stuff)
-		return true;
-
-	while (tmpfs_extra_stuff[i]) {
-		if (unlink(tmpfs_extra_stuff[i]) < 0) {
-			l_error("Failed to remove symlink for %s: %s",
-					tmpfs_extra_stuff[i], strerror(errno));
-
-			return false;
-		}
-
-		i++;
-	}
-
-	return true;
-}
-
-#define CONSOLE_LN_DEFAULT	"\x1B[0m"
-#define CONSOLE_LN_RED		"\x1B[31m"
-#define CONSOLE_LN_GREEN	"\x1B[32m"
-#define CONSOLE_LN_BLACK	"\x1B[30m"
-#define CONSOLE_LN_YELLOW	"\x1B[33m"
-#define CONSOLE_LN_RESET	"\033[0m"
-
-#define CONSOLE_LN_BOLD		"\x1b[1m"
-
-#define CONSOLE_BG_WHITE	"\e[47m"
-#define CONSOLE_BG_DEFAULT	"\e[0m"
-
-enum test_status {
-	TEST_STATUS_STARTED,
-	TEST_STATUS_PASSED,
-	TEST_STATUS_FAILED,
-	TEST_STATUS_TIMEDOUT,
-};
-
-static void print_test_status(char *test_name, enum test_status ts,
-								double interval)
-{
-	const char *clear_line = "\r";
-	int int_len;
-	char *color_str;
-	char *status_str;
-	char *interval_str;
-	char *line_end = "";
-
-	switch (ts) {
-	case TEST_STATUS_STARTED:
-		color_str = CONSOLE_LN_RESET;
-		status_str = "STARTED   ";
-
-		if (strcmp(verbose_opt, "none"))
-			line_end = "\n";
-
-		break;
-	case TEST_STATUS_PASSED:
-		printf("%s", clear_line);
-		color_str = CONSOLE_LN_GREEN;
-		status_str = "PASSED    ";
-		line_end = "\n";
-
-		break;
-	case TEST_STATUS_FAILED:
-		printf("%s", clear_line);
-		color_str = CONSOLE_LN_RED;
-		status_str = "FAILED    ";
-		line_end = "\n";
-
-		break;
-	case TEST_STATUS_TIMEDOUT:
-		printf("%s", clear_line);
-		color_str = CONSOLE_LN_YELLOW;
-		status_str = "TIMED OUT ";
-		line_end = "\n";
-
-		break;
-	}
-
-	if (interval > 0)
-		int_len = snprintf(NULL, 0, "%.3f", interval);
-	else
-		int_len = 3;
-
-	int_len++;
-
-	interval_str = l_malloc(int_len);
-	memset(interval_str, ' ', int_len);
-	interval_str[int_len - 1] = '\0';
-
-	if (interval > 0)
-		sprintf(interval_str, "%.3f sec", interval);
-	else
-		sprintf(interval_str, "%s", "...");
-
-	printf("%s%s%s%-60s%7s%s", color_str, status_str, CONSOLE_LN_RESET,
-		test_name, interval_str, line_end);
-
-	fflush(stdout);
-
-	l_free(interval_str);
-}
-
-static void test_timeout_timer_tick(struct l_timeout *timeout, void *user_data)
-{
-	pid_t *test_exec_pid = (pid_t *) user_data;
-
-	kill_process(*test_exec_pid);
-
-	l_main_quit();
-}
-
-static void test_timeout_signal_handler(uint32_t signo, void *user_data)
-{
-	switch (signo) {
-	case SIGINT:
-	case SIGTERM:
-		l_main_quit();
-		break;
-	}
-}
-
-static pid_t start_execution_timeout_timer(unsigned int max_exec_interval_sec,
-							pid_t *test_exec_pid)
-{
-	struct l_timeout *test_exec_timeout;
-	pid_t test_timer_pid;
-
-	test_timer_pid = fork();
-	if (test_timer_pid < 0) {
-		l_error("Failed to fork new process");
-		return -1;
-	}
-
-	if (test_timer_pid == 0) {
-		if (!l_main_init())
-			exit(EXIT_FAILURE);
-
-		test_exec_timeout =
-			l_timeout_create(max_exec_interval_sec,
-						test_timeout_timer_tick,
-						test_exec_pid,
-						NULL);
-
-		l_main_run_with_signal(test_timeout_signal_handler, NULL);
-
-		l_timeout_remove(test_exec_timeout);
-
-		l_main_exit();
-
-		exit(EXIT_SUCCESS);
-	}
-
-	return test_timer_pid;
-}
-
-struct test_stats {
-	char *config_cycle_name;
-	unsigned int num_passed;
-	unsigned int num_failed;
-	unsigned int num_timedout;
-	double py_run_time;
-};
-
-static void run_py_tests(struct l_settings *hw_settings,
-					struct l_queue *test_queue,
-					struct l_queue *test_stats_queue,
-					const char *test_name)
-{
-	char *argv[3];
-	pid_t test_exec_pid, test_timer_pid = -1;
-	struct timeval time_before, time_after, time_elapsed;
-	unsigned int max_exec_interval;
-	char *py_test = NULL;
-	struct test_stats *test_stats;
-	pid_t monitor_pid = -1;
-
-	if (!l_settings_get_uint(hw_settings, HW_CONFIG_GROUP_SETUP,
-						HW_CONFIG_SETUP_MAX_EXEC_SEC,
-							&max_exec_interval))
-		max_exec_interval = TEST_MAX_EXEC_TIME_SEC;
-
-	l_info(CONSOLE_LN_BOLD "%-10s%-60s%s" CONSOLE_LN_RESET, "Status",
-							"Test", "Duration");
-
-start_next_test:
-
-	if (l_queue_isempty(test_queue))
-		return;
-
-	py_test = (char *) l_queue_pop_head(test_queue);
-	if (!py_test)
-		return;
-
-	if (log) {
-		char *test_path;
-		char *ext;
-		char *full_path;
-
-		test_path = l_strdup_printf("%s/%s", test_name, py_test);
-		ext = strchr(test_path, '.');
-		ext[0] = '\0';
-
-		full_path = l_strdup_printf("%s/%s", log_dir, test_path);
-
-		mkdir(full_path, 0755);
-		if (chown(full_path, log_uid, log_gid) < 0)
-			l_error("chown failed %s", full_path);
-
-		l_free(full_path);
-
-		monitor_pid = start_monitor(test_path);
-
-		l_free(test_path);
-	}
-
-	argv[0] = "python3";
-	argv[1] = py_test;
-	argv[2] = NULL;
-
-	print_test_status(py_test, TEST_STATUS_STARTED, 0);
-	test_exec_pid = execute_program(argv, environ, false, test_name);
-
-	gettimeofday(&time_before, NULL);
-
-	if (!strcmp(gdb_opt, "none"))
-		test_timer_pid = start_execution_timeout_timer(
-				max_exec_interval, &test_exec_pid);
-
-	test_stats = (struct test_stats *) l_queue_peek_tail(test_stats_queue);
-
-	while (true) {
-		pid_t corpse;
-		int status;
-		double interval;
-
-		corpse = waitpid(WAIT_ANY, &status, 0);
-
-		if (corpse < 0 || corpse == 0)
-			continue;
-
-		if (test_exec_pid == corpse) {
-			gettimeofday(&time_after, NULL);
-
-			if (test_timer_pid != -1)
-				kill_process(test_timer_pid);
-
-			timersub(&time_after, &time_before, &time_elapsed);
-			interval = time_elapsed.tv_sec +
-					1e-6 * time_elapsed.tv_usec;
-
-			if (WIFEXITED(status) &&
-					WEXITSTATUS(status) == EXIT_SUCCESS) {
-				print_test_status(py_test, TEST_STATUS_PASSED,
-							interval);
-				test_stats->num_passed++;
-			} else if (WIFSIGNALED(status)) {
-				print_test_status(py_test, TEST_STATUS_TIMEDOUT,
-								interval);
-				test_stats->num_timedout++;
-			} else {
-				print_test_status(py_test, TEST_STATUS_FAILED,
-								interval);
-				test_stats->num_failed++;
-			}
-
-			test_stats->py_run_time += interval;
-
-			break;
-		} else if (WIFSTOPPED(status))
-			l_info("Process %d stopped with signal %d", corpse,
-			       WSTOPSIG(status));
-		else if (WIFCONTINUED(status))
-			l_info("Process %d continued", corpse);
-	}
-
-	l_free(py_test);
-	py_test = NULL;
-
-	if (monitor_pid != -1) {
-		kill_process(monitor_pid);
-		monitor_pid = -1;
-	}
-
-	goto start_next_test;
-}
-
-static void set_config_cycle_info(const char *config_dir_path,
-					struct l_queue *test_stats_queue)
-{
-	char sep_line[80];
-	char *config_name_ptr;
-	struct test_stats *test_stats;
-
-	memset(sep_line, '_', sizeof(sep_line) - 1);
-	sep_line[sizeof(sep_line) - 1] = '\0';
-
-	config_name_ptr = strrchr(config_dir_path, '/');
-	config_name_ptr++;
-
-	l_info("%s", sep_line);
-	l_info(CONSOLE_LN_BOLD "Starting configuration cycle No: %d [%s]"
-		CONSOLE_LN_RESET, l_queue_length(test_stats_queue) + 1,
-							config_name_ptr);
-
-	test_stats = l_new(struct test_stats, 1);
-	test_stats->config_cycle_name = strdup(config_name_ptr);
-
-	l_queue_push_tail(test_stats_queue, test_stats);
-}
-
-static void set_wiphy_list(struct l_queue *wiphy_list)
-{
-	const struct l_queue_entry *wiphy_entry;
-	int size = 32;
-	char *var;
-
-	for (wiphy_entry = l_queue_get_entries(wiphy_list);
-				wiphy_entry; wiphy_entry = wiphy_entry->next) {
-		struct wiphy *wiphy = wiphy_entry->data;
-
-		size += 32 + strlen(wiphy->name);
-		if (wiphy->used_by_hostapd) {
-			size += 32 + strlen(wiphy->interface_name) +
-				strlen(wiphy->hostapd_ctrl_interface) +
-				strlen(wiphy->hostapd_config);
-		}
-	}
-
-	var = alloca(size);
-	size = 0;
-
-	for (wiphy_entry = l_queue_get_entries(wiphy_list);
-				wiphy_entry; wiphy_entry = wiphy_entry->next) {
-		struct wiphy *wiphy = wiphy_entry->data;
-
-		if (size)
-			var[size++] = '\n';
-
-		size += sprintf(var + size, "%s=", wiphy->name);
-
-		if (wiphy->used_by_hostapd)
-			size += sprintf(var + size,
-					"hostapd,name=%s,ctrl_interface=%s,"
-					"config=%s",
-					wiphy->interface_name,
-					wiphy->hostapd_ctrl_interface,
-					wiphy->hostapd_config);
-		else
-			size += sprintf(var + size, "iwd");
-	}
-
-	var[size++] = '\0';
-
-	setenv("TEST_WIPHY_LIST", var, true);
-}
-
-static void set_reg_domain(const char *domain)
-{
-	char *argv[5];
-
-	argv[0] = "iw";
-	argv[1] = "reg";
-	argv[2] = "set";
-	argv[3] = (char *) domain;
-	argv[4] = NULL;
-
-	execute_program(argv, environ, false, NULL);
-}
-
-static void wiphy_up(void *data, void *user_data)
-{
-	struct wiphy *wiphy = data;
-
-	set_interface_state(wiphy->interface_name, true);
-}
-
-static void wiphy_reset(void *data, void *user_data)
-{
-	struct wiphy *wiphy = data;
-
-	wiphy->used_by_hostapd = false;
-
-	l_free(wiphy->hostapd_config);
-	wiphy->hostapd_config = NULL;
-	l_free(wiphy->hostapd_ctrl_interface);
-	wiphy->hostapd_ctrl_interface = NULL;
-}
-
-static void create_network_and_run_tests(void *data, void *user_data)
-{
-	pid_t hostapd_pids[HWSIM_RADIOS_MAX];
-	pid_t iwd_pid = -1;
-	pid_t medium_pid = -1;
-	pid_t ofono_pid = -1;
-	pid_t phonesim_pid = -1;
-	char *config_dir_path;
-	char *iwd_config_dir;
-	char **tmpfs_extra_stuff = NULL;
-	struct l_settings *hw_settings;
-	struct l_queue *test_queue;
-	struct l_queue *test_stats_queue;
-	bool start_iwd_daemon = true;
-	bool needs_hwsim = false;
-	bool ofono_req = false;
-	const char *sim_keys;
-	const char *iwd_ext_options = NULL;
-	const char *reg_domain;
-	int phys_used;
-	int num_radios;
-	struct test_entry *entry = data;
-	char *test_name = NULL;
-
-	memset(hostapd_pids, -1, sizeof(hostapd_pids));
-
-	config_dir_path = (char *) entry->path;
-	test_queue = (struct l_queue *) entry->test_queue;
-	test_stats_queue = (struct l_queue *) user_data;
-
-	if (l_queue_isempty(test_queue)) {
-		l_error("No Python IWD tests have been found in %s",
-							config_dir_path);
-		return;
-	}
-
-	set_config_cycle_info(config_dir_path, test_stats_queue);
-
-	hw_settings = read_hw_config(config_dir_path);
-	if (!hw_settings)
-		return;
-
-	l_info("Configuring network...");
-
-	if (log) {
-		char *log_path;
-
-		test_name = basename(config_dir_path);
-		log_path = l_strdup_printf("%s/%s", log_dir, test_name);
-
-		mkdir(log_path, 0755);
-		if (chown(log_path, log_uid, log_gid) < 0)
-			l_error("chown failed");
-
-		l_free(log_path);
-	}
-
-	if (chdir(config_dir_path) < 0) {
-		l_error("Failed to change to test directory: %s",
-							strerror(errno));
-		goto free_hw_settings;
-	}
-
-	tmpfs_extra_stuff =
-		l_settings_get_string_list(hw_settings, HW_CONFIG_GROUP_SETUP,
-						HW_CONFIG_SETUP_TMPFS_EXTRAS,
-									':');
-
-	sim_keys = l_settings_get_value(hw_settings, HW_CONFIG_GROUP_SETUP,
-								"sim_keys");
-
-	if (sim_keys) {
-		if (!strcmp(sim_keys, "ofono")) {
-			bool ofono_found = false;
-			bool phonesim_found = false;
-
-			if (!system("which ofonod > /dev/null 2>&1"))
-				ofono_found = true;
-
-			if (!system("which phonesim > /dev/null 2>&1"))
-				phonesim_found = true;
-
-			if (!ofono_found || !phonesim_found) {
-				l_info("ofono or phonesim not found, skipping");
-				goto free_tmpfs_extra;
-			}
-
-			ofono_req = true;
-			iwd_ext_options = "--plugin=ofono";
-		} else {
-			setenv("IWD_SIM_KEYS", sim_keys, true);
-			iwd_ext_options = "--plugin=sim_hardcoded";
-		}
-	}
-
-	/* turn on/off timeouts if GDB is being used */
-	if (!strcmp(gdb_opt, "none"))
-		setenv("IWD_TEST_TIMEOUTS", "on", true);
-	else
-		setenv("IWD_TEST_TIMEOUTS", "off", true);
-
-	if (!create_tmpfs_extra_stuff(tmpfs_extra_stuff))
-		goto remove_abs_paths;
-
-	l_settings_get_int(hw_settings, HW_CONFIG_GROUP_SETUP,
-					HW_CONFIG_SETUP_NUM_RADIOS,
-					&num_radios);
-
-	if (!native_hw) {
-		reg_domain = l_settings_get_value(hw_settings,
-						HW_CONFIG_GROUP_SETUP,
-						HW_CONFIG_SETUP_REG_DOMAIN);
-		if (reg_domain)
-			set_reg_domain(reg_domain);
-
-		wiphy_list = l_queue_new();
-
-		if (!configure_hw_radios(hw_settings, wiphy_list))
-			goto remove_abs_paths;
-
-		medium_pid = register_hwsim_as_trans_medium();
-		if (medium_pid < 0)
-			goto remove_abs_paths;
-
-		if (check_verbosity("hwsim")) {
-			list_hwsim_radios();
-			list_interfaces();
-		}
-	} else {
-		int len;
-
-		l_settings_get_bool(hw_settings, HW_CONFIG_GROUP_SETUP,
-				HW_CONFIG_SETUP_NEEDS_HWSIM, &needs_hwsim);
-
-		/* Skip test that require hwsim dbus APIs (hwsim not running) */
-		if (needs_hwsim) {
-			l_error("test requires hwsim, skipping");
-			goto remove_abs_paths;
-		}
-
-		len = l_queue_length(wiphy_list);
-
-		/* Skip tests that need more radios than we have */
-		if (num_radios > len) {
-			l_error("test requires %d radios, only %d found",
-					num_radios, len);
-			goto remove_abs_paths;
-		}
-
-		l_queue_foreach(wiphy_list, wiphy_up, NULL);
-	}
-
-	if (check_verbosity("tls"))
-		setenv("IWD_TLS_DEBUG", "on", true);
-
-	if (!configure_hostapd_instances(hw_settings, config_dir_path,
-						wiphy_list, hostapd_pids,
-						&phys_used))
-		goto exit_hostapd;
-
-	l_settings_get_bool(hw_settings, HW_CONFIG_GROUP_SETUP,
-				HW_CONFIG_SETUP_START_IWD, &start_iwd_daemon);
-
-	if (start_iwd_daemon) {
-		/*
-		 * In native mode we may have more radios than a test actually
-		 * needs. This would result in IWD managing all phys that
-		 * hostapd wasn't using, which could throw off test results.
-		 * By passing the number of phys the test expects IWD to have
-		 * we can leave the remaining (unneeded) phys unmanaged.
-		 */
-		int iwd_phys = num_radios - phys_used;
-
-		iwd_config_dir =
-			l_settings_get_string(hw_settings,
-						HW_CONFIG_GROUP_SETUP,
-						HW_CONFIG_SETUP_IWD_CONF_DIR);
-		if (!iwd_config_dir)
-			iwd_config_dir = "/tmp";
-
-		iwd_pid = start_iwd(iwd_config_dir, wiphy_list,
-				iwd_ext_options, iwd_phys, test_name);
-
-		if (iwd_pid == -1)
-			goto exit_hostapd;
-	} else {
-		/* tells pytest to start iwd with valgrind */
-		if (valgrind)
-			setenv("IWD_TEST_VALGRIND", "on", true);
-	}
-
-	if (ofono_req) {
-		phonesim_pid = start_phonesim(test_name);
-		ofono_pid = start_ofono(test_name);
-	}
-
-	set_wiphy_list(wiphy_list);
-
-	if (!shell)
-		run_py_tests(hw_settings, test_queue, test_stats_queue,
-				test_name);
-	else {
-		if (system("/bin/sh"))
-			l_info("executing /bin/sh failed");
-	}
-
-	l_info("Destructing network...");
-
-	/* Script has responsibility to cleanup any iwd instances it started */
-	if (iwd_pid > 0)
-		terminate_iwd(iwd_pid);
-
-	/* /tmp/valgrind.log will only exist without logging turned on */
-	if (valgrind && !log) {
-		if (system("cat /tmp/valgrind.log"))
-			l_info("cat /tmp/valgrind.log failed");
-
-		if (system("echo \"\" > /tmp/valgrind.log"))
-			l_info("Failed to reset /tmp/valgrind.log");
-	}
-
-	if (log) {
-		L_AUTO_FREE_VAR(char *, dmesg);
-		L_AUTO_FREE_VAR(char *, kernel_log);
-
-		kernel_log = l_strdup_printf("%s/kernel.log", log_dir);
-		dmesg = l_strdup_printf("dmesg > %s", kernel_log);
-
-		if (system(dmesg))
-			l_error("dmesg failed");
-		if (chown(kernel_log, log_uid, log_gid))
-			l_error("chown failed");
-	}
-
-	if (ofono_req) {
-		loopback_started = false;
-		stop_ofono(ofono_pid);
-		stop_phonesim(phonesim_pid);
-	}
-
-exit_hostapd:
-	destroy_hostapd_instances(hostapd_pids);
-
-	if (!native_hw)
-		terminate_medium(medium_pid);
-
-remove_abs_paths:
-	remove_absolute_path_dirs(tmpfs_extra_stuff);
-
-	/*
-	 * If running in hwsim mode, we want to completely free/destroy the
-	 * wiphy list since it will be re-populated on the next test. For the
-	 * native case we want to reset the list as if it was freshly
-	 * discovered. This ensures that all the hostapd flags get reset.
-	 */
-	if (!native_hw)
-		l_queue_destroy(wiphy_list, wiphy_free);
-	else
-		l_queue_foreach(wiphy_list, wiphy_reset, NULL);
-
-free_tmpfs_extra:
-	l_strfreev(tmpfs_extra_stuff);
-free_hw_settings:
-	l_settings_free(hw_settings);
-}
-
-struct stat_totals {
-	unsigned int total_passed;
-	unsigned int total_failed;
-	unsigned int total_timedout;
-	double total_duration;
-};
-
-static void print_test_stat(void *data, void *user_data)
-{
-	struct test_stats *test_stats;
-	struct stat_totals *stat_totals;
-	char *str_runtime, *str_passed, *str_failed, *str_timedout;
-
-	test_stats = (struct test_stats *) data;
-	stat_totals = (struct stat_totals *) user_data;
-
-	stat_totals->total_duration	+= test_stats->py_run_time;
-	stat_totals->total_passed	+= test_stats->num_passed;
-	stat_totals->total_failed	+= test_stats->num_failed;
-	stat_totals->total_timedout	+= test_stats->num_timedout;
-
-	if (test_stats->py_run_time)
-		str_runtime = l_strdup_printf("| %9.3f sec",
-						test_stats->py_run_time);
-	else
-		str_runtime = l_strdup_printf("| %9s", "Skipped");
-
-	if (test_stats->num_passed)
-		str_passed = l_strdup_printf(" %6d ", test_stats->num_passed);
-	else
-		str_passed = l_strdup_printf(" %6c ", '-');
-
-	if (test_stats->num_failed)
-		str_failed = l_strdup_printf(" %6d ", test_stats->num_failed);
-	else
-		str_failed = l_strdup_printf(" %6c ", '-');
-
-	if (test_stats->num_timedout)
-		str_timedout = l_strdup_printf(" %9d ",
-						test_stats->num_timedout);
-	else
-		str_timedout = l_strdup_printf(" %9c ", '-');
-
-	l_info(CONSOLE_LN_BOLD "%27s "
-			CONSOLE_LN_DEFAULT "|" CONSOLE_LN_GREEN "%s"
-			CONSOLE_LN_DEFAULT "|" CONSOLE_LN_RED "%s"
-			CONSOLE_LN_DEFAULT "|" CONSOLE_LN_YELLOW "%s"
-			CONSOLE_LN_RESET "%s", test_stats->config_cycle_name,
-			str_passed, str_failed, str_timedout, str_runtime);
-
-	l_free(str_passed);
-	l_free(str_failed);
-	l_free(str_timedout);
-	l_free(str_runtime);
-}
-
-static void print_results(struct l_queue *test_stat_queue)
-{
-	struct stat_totals stat_totals = { 0, 0, 0, 0 };
-	char sep_line[80];
-
-	memset(sep_line, '_', sizeof(sep_line) - 1);
-	sep_line[sizeof(sep_line) - 1] = '\0';
-
-	l_info("%s\n" CONSOLE_LN_RESET, sep_line);
-	l_info("%27s " CONSOLE_LN_DEFAULT "|" CONSOLE_LN_GREEN " %s "
-		CONSOLE_LN_DEFAULT "|" CONSOLE_LN_RED " %5s "
-		CONSOLE_LN_DEFAULT "|" CONSOLE_LN_YELLOW " %9s "
-		CONSOLE_LN_RESET "| Duration",
-		"Configuration cycle", "PASSED", "FAILED", "TIMED OUT");
-
-	memset(sep_line, '-', sizeof(sep_line) - 1);
-	sep_line[sizeof(sep_line) - 1] = '\0';
-	l_info("%s" CONSOLE_LN_RESET, sep_line);
-
-	l_queue_foreach(test_stat_queue, print_test_stat, &stat_totals);
-
-	l_info("%s" CONSOLE_LN_RESET, sep_line);
-	l_info("%27s "
-		CONSOLE_LN_DEFAULT "|" CONSOLE_LN_GREEN " %6d "
-		CONSOLE_LN_DEFAULT "|" CONSOLE_LN_RED " %6d "
-		CONSOLE_LN_DEFAULT "|" CONSOLE_LN_YELLOW " %9d "
-		CONSOLE_LN_RESET "| %9.3f sec",
-		"Total", stat_totals.total_passed, stat_totals.total_failed,
-			stat_totals.total_timedout, stat_totals.total_duration);
-
-	memset(sep_line, '_', sizeof(sep_line) - 1);
-	sep_line[sizeof(sep_line) - 1] = '\0';
-	l_info("%s" CONSOLE_LN_RESET, sep_line);
-}
-
-static void test_stat_queue_entry_destroy(void *data)
-{
-	struct test_stats *ts;
-
-	ts = (struct test_stats *) data;
-
-	l_free(ts->config_cycle_name);
-	l_free(ts);
-}
-
-static void free_test_entry(void *data)
-{
-	struct test_entry *entry = data;
-
-	l_free(entry->path);
-	l_free(entry);
-}
-
-static void run_auto_tests(void)
-{
-	L_AUTO_FREE_VAR(char*, test_home_path) = NULL;
-	L_AUTO_FREE_VAR(char*, env_path) = NULL;
-	int i;
-	struct l_queue *test_config_queue;
-	struct l_queue *test_stat_queue;
-	char **test_config_dirs;
-
-	if (log) {
-		if (mount("logdir", log_dir, "9p", 0,
-					"trans=virtio,version=9p2000.L") < 0) {
-			l_error("Mounting %s failed", log_dir);
-			return;
-		}
-	}
-
-	env_path = l_strdup_printf("%s/src:%s/tools:%s", top_level_path,
-					top_level_path, getenv("PATH"));
-
-	setenv("PATH", env_path, true);
-
-	test_home_path = l_strdup_printf("%s/%s", top_level_path,
-						TEST_TOP_DIR_DEFAULT_NAME);
-
-	if (!path_exist(test_home_path)) {
-		l_error("Test directory %s does not exist", test_home_path);
-		return;
-	}
-
-	test_config_queue = l_queue_new();
-	if (!test_config_queue)
-		return;
-
-	test_config_dirs = l_strsplit(test_action_params, ',');
-
-	if (test_config_dirs[0]) {
-		i = 0;
-
-		while (test_config_dirs[i]) {
-			if (strchr(test_config_dirs[i], '/')) {
-				if (!find_test_configuration(
-							test_config_dirs[i], 1,
-							test_config_queue))
-					goto exit;
-			} else {
-				char *config_dir_path;
-
-				config_dir_path =
-					l_strdup_printf("%s/%s", test_home_path,
-							test_config_dirs[i]);
-
-				if (!find_test_configuration(config_dir_path, 1,
-							test_config_queue)) {
-					l_free(config_dir_path);
-
-					goto exit;
-				}
-
-				l_free(config_dir_path);
-			}
-
-			i++;
-		}
-	} else {
-		/*
-		 * --shell without any specific tests implies 'shell' test
-		 */
-		if (shell) {
-			char *config_dir_path;
-			config_dir_path = l_strdup_printf("%s/shell",
-								test_home_path);
-
-			if (!find_test_configuration(config_dir_path, 1,
-							test_config_queue)) {
-				l_free(config_dir_path);
-				goto exit;
-			}
-
-			l_free(config_dir_path);
-		} else {
-			l_info("Automatic test execution requested");
-			l_info("Searching for the test configurations...");
-
-			if (!find_test_configuration(test_home_path, 0,
-							test_config_queue))
-				goto exit;
-		}
-	}
-
-	if (l_queue_isempty(test_config_queue)) {
-		l_error("No test configuration discovered");
-		goto exit;
-	}
-
-	create_dbus_system_conf();
-
-	if (!start_dbus_daemon())
-		goto exit;
-
-	if (!start_haveged()) {
-		l_error("Failed to start haveged");
-		goto exit;
-	}
-
-	test_stat_queue = l_queue_new();
-
-	l_queue_foreach(test_config_queue, create_network_and_run_tests,
-							test_stat_queue);
-
-	print_results(test_stat_queue);
-
-	l_queue_destroy(test_stat_queue, test_stat_queue_entry_destroy);
-
-exit:
-	l_strfreev(verbose_apps);
-	l_strfreev(test_config_dirs);
-	l_queue_destroy(test_config_queue, free_test_entry);
-}
-
-static void run_unit_tests(void)
-{
-	DIR *d;
-	struct dirent *dirent;
-	char *argv[2];
-	char *unit_test_abs_path = NULL;
-	char **unit_tests = NULL;
-
-	if (strcmp(test_action_params, "")) {
-		unit_tests = l_strsplit(test_action_params, ',');
-
-		if (!unit_tests || !unit_tests[0])
-			goto exit;
-	}
-
-	if (chdir(top_level_path) < 0)
-		goto exit;
-
-	d = opendir("unit/");
-	if (!d)
-		goto exit;
-
-	while ((dirent = readdir(d)) != NULL) {
-		struct stat st;
-
-		if (dirent->d_type != DT_REG)
-			continue;
-
-		unit_test_abs_path = l_strdup_printf("%s%s%s", top_level_path,
-						"/unit/", dirent->d_name);
-
-		if (stat(unit_test_abs_path, &st) < 0)
-			goto next;
-
-		if (!(st.st_mode & S_IEXEC))
-			goto next;
-
-		if (unit_tests) {
-			if (!l_strv_contains(unit_tests, dirent->d_name))
-				goto next;
-		}
-
-		argv[0] = unit_test_abs_path;
-		argv[1] = NULL;
-
-		l_info("\n---------- Unit %s ----------", dirent->d_name);
-		execute_program(argv, environ, true, NULL);
-
-next:
-		l_free(unit_test_abs_path);
-	}
-
-	closedir(d);
-
-exit:
-	l_strfreev(unit_tests);
-}
-
-static bool wiphy_match(const void *a, const void *b)
-{
-	const struct wiphy *wiphy = a;
-	int id = L_PTR_TO_INT(b);
-
-	return (wiphy->id == id);
-}
-
-static struct wiphy *wiphy_find(int wiphy_id)
-{
-	return l_queue_find(wiphy_list, wiphy_match, L_INT_TO_PTR(wiphy_id));
-}
-
-static void parse_supported_iftypes(uint16_t *iftypes,
-						struct l_genl_attr *attr)
-{
-	uint16_t type, len;
-	const void *data;
-
-	while (l_genl_attr_next(attr, &type, &len, &data)) {
-		/*
-		 * NL80211_IFTYPE_UNSPECIFIED can be ignored, so we start
-		 * at the first bit
-		 */
-		if (type > sizeof(uint16_t) * 8) {
-			l_warn("unsupported iftype: %u", type);
-			continue;
-		}
-
-		*iftypes |= 1 << (type - 1);
-	}
-}
-
-static void wiphy_dump_callback(struct l_genl_msg *msg, void *user_data)
-{
-	struct wiphy *wiphy;
-	struct l_genl_attr attr;
-	struct l_genl_attr nested;
-	uint32_t id = UINT32_MAX;
-	uint16_t type, len;
-	const void *data;
-	const char *name = NULL;
-	uint32_t name_len = 0;
-	uint16_t iftypes = 0;
-
-	if (!l_genl_attr_init(&attr, msg))
-		return;
-
-	while (l_genl_attr_next(&attr, &type, &len, &data)) {
-		switch (type) {
-		case NL80211_ATTR_WIPHY:
-			if (len != sizeof(uint32_t))
-				return;
-
-			id = *((uint32_t *) data);
-
-			if (wiphy_find(id))
-				return;
-
-			break;
-		case NL80211_ATTR_WIPHY_NAME:
-			if (len > sizeof(((struct wiphy *) 0)->name))
-				return;
-
-			name = data;
-			name_len = len;
-
-			break;
-		case NL80211_ATTR_SUPPORTED_IFTYPES:
-			if (l_genl_attr_recurse(&attr, &nested))
-				parse_supported_iftypes(&iftypes, &nested);
-
-			break;
-		}
-	}
-
-	if (id == UINT32_MAX || !name)
-		return;
-
-	wiphy = l_new(struct wiphy, 1);
-	strncpy(wiphy->name, name, name_len);
-	wiphy->id = id;
-	wiphy->can_ap = iftypes & (1 << NL80211_IFTYPE_AP);
-
-	l_queue_push_tail(wiphy_list, wiphy);
-}
-
-static void iface_dump_callback(struct l_genl_msg *msg, void *user_data)
-{
-	struct l_genl_attr attr;
-	uint16_t type, len;
-	const void *data;
-	const char *ifname = NULL;
-	struct wiphy *wiphy = NULL;
-
-	if (!l_genl_attr_init(&attr, msg))
-		return;
-
-	while (l_genl_attr_next(&attr, &type, &len, &data)) {
-		switch (type) {
-
-		case NL80211_ATTR_IFNAME:
-			if (len > 16) {
-				l_warn("Invalid interface name attribute");
-				return;
-			}
-
-			ifname = data;
-			break;
-
-		case NL80211_ATTR_WIPHY:
-			if (len != sizeof(uint32_t)) {
-				l_warn("Invalid wiphy attribute");
-				return;
-			}
-
-			wiphy = wiphy_find(*((uint32_t *) data));
-			break;
-		}
-	}
-
-	if (!ifname || !wiphy)
-		return;
-
-	wiphy->interface_name = l_strdup(ifname);
-	wiphy->interface_created = false;
-
-	l_info("Discovered interface %s", wiphy->interface_name);
-}
-
-struct nl_data {
-	struct l_genl *genl;
-	struct l_genl_family *nl80211;
-};
-
-static void iface_dump_done(void *user_data)
-{
-	struct nl_data *data = user_data;
-
-	l_debug("Interface discovery complete, running tests");
-
-	list_interfaces();
-
-	run_auto_tests();
-
-	l_queue_destroy(wiphy_list, wiphy_free);
-
-	l_genl_family_free(data->nl80211);
-	l_genl_unref(data->genl);
-	l_free(data);
-
-	l_main_quit();
-}
-
-static void wiphy_dump_done(void *user_data)
-{
-	struct nl_data *data = user_data;
-	struct l_genl_msg *msg;
-
-	l_debug("Wiphy discovery complete, discovering interfaces");
-
-	msg = l_genl_msg_new(NL80211_CMD_GET_INTERFACE);
-	if (!l_genl_family_dump(data->nl80211, msg, iface_dump_callback,
-						data, iface_dump_done))
-		l_error("Getting all interface information failed");
-}
-
-static void nl80211_requested(const struct l_genl_family_info *info,
-							void *user_data)
-{
-	struct nl_data *data = user_data;
-	struct l_genl_msg *msg;
-
-	if (info == NULL) {
-		l_info("No nl80211 family found");
-		goto done;
-	}
-
-	l_debug("Found nl80211 interface");
-
-	data->nl80211 = l_genl_family_new(data->genl, NL80211_GENL_NAME);
-	wiphy_list = l_queue_new();
-
-	msg = l_genl_msg_new(NL80211_CMD_GET_WIPHY);
-	if (!l_genl_family_dump(data->nl80211, msg, wiphy_dump_callback,
-						data, wiphy_dump_done))
-		l_error("Getting all wiphy devices failed");
-
-	return;
-done:
-	l_main_quit();
-}
-
-static void start_hw_discovery(void)
-{
-	struct nl_data *data = l_new(struct nl_data, 1);
-
-	data->genl = l_genl_new();
-	l_genl_request_family(data->genl, NL80211_GENL_NAME,
-				nl80211_requested, data, NULL);
-	/*
-	 * This is somewhat of a mystery, but it appears that
-	 * calling lshw causes the OS to re-enumerate the USB
-	 * bus. Without this no USB adapters are found when
-	 * doing the wiphy/iface dump from nl80211.
-	 *
-	 * This also conveniently prints all the network
-	 * adapters and their iface name, so its much easier
-	 * to know which adapter are being used by iwd/hostapd
-	 * after the test.
-	 */
-	if (system("lshw -C network"))
-		l_info("lshw failed");
-
-	l_main_run();
-}
-
-static void run_tests(void)
-{
-	char cmdline[CMDLINE_MAX], *ptr, *cmds;
-	char *test_action_str;
-	FILE *fp;
-	int i;
-
-	fp = fopen("/proc/cmdline", "re");
-
-	if (!fp) {
-		l_error("Failed to open kernel command line");
-		return;
-	}
-
-	ptr = fgets(cmdline, sizeof(cmdline), fp);
-	fclose(fp);
-
-	if (!ptr) {
-		l_error("Failed to read kernel command line");
-		return;
-	}
-
-	ptr = strstr(cmdline, "LOG_GID=");
-	if (ptr) {
-		*ptr = '\0';
-		test_action_str = ptr + 9;
-		ptr = strchr(test_action_str, '\'');
-		*ptr = '\0';
-		log_gid = atoi(test_action_str);
-	}
-
-	ptr = strstr(cmdline, "LOG_UID=");
-	if (ptr) {
-		*ptr = '\0';
-		test_action_str = ptr + 9;
-		ptr = strchr(test_action_str, '\'');
-		*ptr = '\0';
-		log_uid = atoi(test_action_str);
-	}
-
-	ptr = strstr(cmdline, "LOG_PATH=");
-	if (ptr) {
-		*ptr = '\0';
-		test_action_str = ptr + 10;
-
-		ptr = strchr(test_action_str, '\'');
-		*ptr = '\0';
-
-		if (strcmp(test_action_str, "none")) {
-			log = true;
-			strcpy(log_dir, test_action_str);
-		}
-	}
-
-	ptr = strstr(cmdline, "SHELL=");
-	if (ptr) {
-		*ptr = '\0';
-		test_action_str = ptr + 6;
-
-		shell = atoi(test_action_str);
-	}
-
-	ptr = strstr(cmdline, "HW=");
-	if (ptr) {
-		*ptr = '\0';
-		test_action_str = ptr + 4;
-
-		ptr = strchr(test_action_str, '\'');
-		if (ptr)
-			*ptr = '\0';
-
-		if (!strcmp(test_action_str, "virtual"))
-			native_hw = false;
-		else
-			native_hw = true;
-	}
-
-	ptr = strstr(cmdline, "GDB=");
-	if (ptr) {
-		*ptr = '\0';
-		test_action_str = ptr + 5;
-
-		ptr = strchr(test_action_str, '\'');
-		*ptr = '\0';
-		gdb_opt = l_strdup(test_action_str);
-	}
-
-	ptr = strstr(cmdline, "VALGRIND=");
-	if (ptr) {
-		char *end;
-		unsigned long v;
-
-		*ptr = '\0';
-		test_action_str = ptr + 9;
-		v = strtoul(test_action_str, &end, 10);
-		if ((v != 0 && v != 1) || end != test_action_str + 1) {
-			l_error("malformed valgrind option");
-			return;
-		}
-
-		valgrind = (bool) v;
-	}
-
-	ptr = strstr(cmdline, "PATH=");
-	if (!ptr) {
-		l_error("No $PATH section found");
-		return;
-	}
-
-	*ptr = '\0';
-	test_action_str = ptr + 6;
-	ptr = strchr(test_action_str, '\'');
-	*ptr = '\0';
-	l_info("%s", test_action_str);
-	setenv("PATH", test_action_str, true);
-
-	ptr = strstr(cmdline, "TESTARGS=");
-
-	if (!ptr) {
-		l_error("No test command section found");
-		return;
-	}
-
-	cmds = ptr + 10;
-	ptr = strchr(cmds, '\'');
-
-	if (!ptr) {
-		l_error("Malformed test command section");
-		return;
-	}
-
-	*ptr = '\0';
-
-	ptr = strstr(cmdline, "TEST_ACTION_PARAMS=");
-
-	if (ptr) {
-		test_action_params = ptr + 20;
-		ptr = strchr(test_action_params, '\'');
-
-		if (!ptr) {
-			l_error("Malformed test action parameters section");
-			return;
-		}
-
-		*ptr = '\0';
-	}
-
-	ptr = strstr(cmdline, "TEST_ACTION=");
-
-	if (ptr) {
-		test_action_str = ptr + 12;
-		ptr = strchr(test_action_str, ' ');
-
-		if (!ptr) {
-			l_error("Malformed test action parameters section");
-			return;
-		}
-
-		*ptr = '\0';
-
-		test_action = (enum action) atoi(test_action_str);
-	}
-
-	ptr = strstr(cmdline, "DEBUG_FILTER=");
-
-	if (ptr) {
-		debug_filter = ptr + 14;
-
-		ptr = strchr(debug_filter, '\'');
-
-		if (!ptr) {
-			l_error("Malformed debug filter section");
-			return;
-		}
-
-		*ptr = '\0';
-
-		if (debug_filter[0] != '\0') {
-			enable_debug = true;
-			l_debug_enable(debug_filter);
-			setenv("HWSIM_DEBUG", "", true);
-		}
-	}
-
-	ptr = strstr(cmdline, "TESTVERBOUT=");
-
-	if (ptr) {
-		verbose_opt = ptr + 13;
-
-		ptr = strchr(verbose_opt, '\'');
-		if (!ptr) {
-			l_error("Malformed verbose parameter");
-			return;
-		}
-
-		*ptr = '\0';
-
-		l_info("Enable verbose output for %s", verbose_opt);
-
-		verbose_apps = l_strsplit(verbose_opt, ',');
-	}
-
-	ptr = strstr(cmdline, "TESTHOME=");
-
-	if (ptr) {
-		exec_home = ptr + 4;
-		ptr = strpbrk(exec_home + 9, " \r\n");
-
-		if (ptr)
-			*ptr = '\0';
-	}
-
-	ptr = strrchr(exec_home, '/');
-
-	if (!ptr)
-		exit(EXIT_FAILURE);
-
-	i = ptr - exec_home;
-
-	strncpy(top_level_path, exec_home + 5, i - 5);
-	top_level_path[i - 5] = '\0';
-
-	switch (test_action) {
-	case ACTION_AUTO_TEST:
-		if (native_hw)
-			start_hw_discovery();
-		else
-			run_auto_tests();
-		break;
-	case ACTION_UNIT_TEST:
-		run_unit_tests();
-		break;
-	}
-}
-
-static void usage(void)
-{
-	l_info("test-runner - Automated test execution utility\n"
-		"Usage:\n");
-	l_info("\ttest-runner [options] [--] <command> [args]\n");
-	l_info("Options:\n"
-		"\t-q, --qemu <path>	QEMU binary\n"
-		"\t-k, --kernel <image>	Kernel image (bzImage)\n"
-		"\t-v, --verbose <apps>	Comma separated list of "
-						"applications to enable\n"
-						"\t\t\t\tverbose output\n"
-		"\t-h, --help		Show help options\n"
-		"\t-V, --valgrind		Run valgrind on iwd. Note: \"-v"
-						" iwd\" is required\n"
-						"\t\t\t\tto see valgrind"
-						" output\n"
-		"\t-g, --gdb <iwd|hostapd>	Run gdb on the specified"
-						" executable\n"
-		"\t-w, --hw <config>	Run using a physical hardware "
-					"configuration\n"
-		"\t-s, --shell		Boot into shell. If -A is used the"
-					" environment\n"
-					"\t\t\t\twill be setup exactly as it is"
-					" in the test,\n"
-					"\t\t\t\tbut no test will be run. If no"
-					" test is specified\n"
-					"\t\t\t\tthe 'shell' test"
-					" will be used\n"
-		"\t-l, --log <dir>		Directory used for log output. "
-					"This option sets \n"
-					"\t\t\t\t--verbose on all apps");
-	l_info("Commands:\n"
-		"\t-A, --auto-tests <dirs>	Comma separated list of the "
-						"test configuration\n\t\t\t\t"
-						"directories to run\n"
-		"\t-U, --unit-tests <tests>	Comma separated list of the "
-						"unit tests to run\n");
-}
-
-static const struct option main_options[] = {
-	{ "auto-tests",	required_argument, NULL, 'A' },
-	{ "unit-tests",	optional_argument, NULL, 'U' },
-	{ "qemu",	required_argument, NULL, 'q' },
-	{ "kernel",	required_argument, NULL, 'k' },
-	{ "verbose",	required_argument, NULL, 'v' },
-	{ "debug",	optional_argument, NULL, 'd' },
-	{ "gdb",	required_argument, NULL, 'g' },
-	{ "valgrind",	no_argument,       NULL, 'V' },
-	{ "hw",		required_argument, NULL, 'w' },
-	{ "shell",	optional_argument, NULL, 's' },
-	{ "log",	required_argument, NULL, 'l' },
-	{ "help",	no_argument,       NULL, 'h' },
-	{ }
-};
-
-int main(int argc, char *argv[])
-{
-	uint8_t actions = 0;
-	struct tm *timeinfo;
-	time_t t;
-	char *gid;
-	char *uid;
-
-	l_log_set_stderr();
-
-	if (getpid() == 1 && getppid() == 0) {
-		if (!l_main_init())
-			return EXIT_FAILURE;
-
-		prepare_sandbox();
-
-		run_tests();
-
-		sync();
-		l_info("Done running tests. Rebooting...");
-
-		reboot(RB_AUTOBOOT);
-		return EXIT_SUCCESS;
-	}
-
-	for (;;) {
-		int opt;
-
-		opt = getopt_long(argc, argv, "A:q:k:v:g:sl:UVdh", main_options,
-									NULL);
-		if (opt < 0)
-			break;
-
-		switch (opt) {
-		case 'A':
-			test_action = ACTION_AUTO_TEST;
-			test_action_params = optarg;
-			actions++;
-			break;
-		case 'U':
-			test_action = ACTION_UNIT_TEST;
-			test_action_params = optarg;
-			actions++;
-			break;
-		case 'q':
-			qemu_binary = optarg;
-			break;
-		case 'k':
-			kernel_image = optarg;
-			break;
-		case 'd':
-			enable_debug = true;
-
-			if (optarg)
-				debug_filter = optarg;
-			else
-				debug_filter = "*";
-
-			l_debug_enable(debug_filter);
-			break;
-		case 'v':
-			verbose_opt = optarg;
-			verbose_apps = l_strsplit(optarg, ',');
-			break;
-		case 'V':
-			valgrind = true;
-			break;
-		case 'g':
-			gdb_opt = optarg;
-			if (!gdb_opt || (strcmp(gdb_opt, "iwd") &&
-					strcmp(gdb_opt, "hostapd") &&
-					strcmp(gdb_opt, "hwsim"))) {
-				l_error("--gdb can only be used with iwd"
-					", hwsim or hostapd");
-				return EXIT_FAILURE;
-			}
-			break;
-		case 'w':
-			hw_config = l_settings_new();
-			if (!l_settings_load_from_file(hw_config, optarg)) {
-				l_error("could not read hw config from %s",
-						optarg);
-				l_settings_free(hw_config);
-				return EXIT_FAILURE;
-			}
-			break;
-		case 's':
-			shell = true;
-			break;
-		case 'l':
-			/*
-			 * Setup the log directory. This is created under the
-			 * passed in log dir (--log) in the format:
-			 * <logdir>/run-<year>-<month>-<day>-<PID>
-			 *
-			 * The created log dir is then chown'ed to the user
-			 * who started test-runner, as are all files created
-			 * under this directory.
-			 */
-			log = true;
-
-			if (!optarg)
-				optarg = ".";
-
-			time(&t);
-			timeinfo = localtime(&t);
-
-			gid = getenv("SUDO_GID");
-			uid = getenv("SUDO_UID");
-
-			if (!gid || !uid) {
-				log_gid = getgid();
-				log_uid = getuid();
-			} else {
-				log_gid = strtol(gid, NULL, 10);
-				log_uid = strtol(uid, NULL, 10);
-			}
-
-			snprintf(log_dir, sizeof(log_dir), "%s/run-%d-%d-%d-%d",
-					optarg, timeinfo->tm_year + 1900,
-					timeinfo->tm_mon + 1, timeinfo->tm_mday,
-					getpid());
-			mkdir(log_dir, 0755);
-
-			if (chown(log_dir, log_uid, log_gid) < 0)
-				l_error("failed to fchown %s", log_dir);
-
-			break;
-		case 'h':
-			usage();
-			return EXIT_SUCCESS;
-		default:
-			return EXIT_FAILURE;
-		}
-	}
-
-	if (argc - optind > 0) {
-		l_error("Invalid command line parameters");
-		return EXIT_FAILURE;
-	}
-
-	if (actions > 1) {
-		l_error("Only one action can be specified");
-		return EXIT_FAILURE;
-	}
-
-	if (!actions)
-		test_action = ACTION_AUTO_TEST;
-
-	own_binary = argv[0];
-	test_argv = argv + optind;
-	test_argc = argc - optind;
-
-	if (!qemu_binary) {
-		qemu_binary = find_qemu();
-		if (!qemu_binary) {
-			l_error("No default QEMU binary found");
-			return EXIT_FAILURE;
-		}
-	}
-
-	if (!kernel_image) {
-		kernel_image = find_kernel();
-		if (!kernel_image) {
-			l_error("No default kernel image found");
-			return EXIT_FAILURE;
-		}
-	}
-
-	l_info("Using QEMU binary %s", qemu_binary);
-	l_info("Using kernel image %s", kernel_image);
-
-	if (!start_qemu())
-		return EXIT_FAILURE;
-
-	return EXIT_SUCCESS;
-}
-- 
2.21.1

  parent reply	other threads:[~2020-08-28 16:40 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-08-28 16:40 [PATCH v2 00/15] Test Runner rewrite James Prestwood
2020-08-28 16:40 ` [PATCH v2 01/15] auto-t: prepare autotests for test-runner re-write James Prestwood
2020-08-28 16:40 ` [PATCH v2 02/15] auto-t: introduce pure python " James Prestwood
2020-08-28 16:40 ` [PATCH v2 03/15] auto-t: hostapd.py: update to work with test-runner rewrite James Prestwood
2020-08-28 16:40 ` [PATCH v2 04/15] auto-t: testutil.py: " James Prestwood
2020-08-28 16:40 ` [PATCH v2 05/15] auto-t: ofono.py: fix timeout cleanup and wait for service James Prestwood
2020-08-28 16:40 ` [PATCH v2 06/15] auto-t: iwd.py: update to work with test-runner rewrite James Prestwood
2020-08-28 16:40 ` [PATCH v2 07/15] auto-t: iwd.py: fix multiple timeout cleanup issues James Prestwood
2020-08-28 16:40 ` [PATCH v2 08/15] auto-t: remove wiphy.py James Prestwood
2020-08-28 16:40 ` [PATCH v2 09/15] auto-t: fix hidden network test James Prestwood
2020-08-28 16:40 ` [PATCH v2 10/15] auto-t: fix testSAE autoconnect_test.py James Prestwood
2020-08-28 16:40 ` [PATCH v2 11/15] auto-t: skip ofono tests if ofonod isn't running James Prestwood
2020-08-28 16:40 ` [PATCH v2 12/15] auto-t: replace hard-coded interfaces James Prestwood
2020-08-28 16:40 ` [PATCH v2 13/15] auto-t: remove device.wait_for_connected James Prestwood
2020-08-28 16:40 ` James Prestwood [this message]
2020-08-28 16:40 ` [PATCH v2 15/15] doc: update test runner docs James Prestwood

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200828164050.1456-15-prestwoj@gmail.com \
    --to=prestwoj@gmail.com \
    --cc=iwd@lists.01.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox