qemu/tests/test-util-sockets.c
<<
>>
Prefs
   1/*
   2 * Tests for util/qemu-sockets.c
   3 *
   4 * Copyright 2018 Red Hat, Inc.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this library; if not, see <http://www.gnu.org/licenses/>.
  18 *
  19 */
  20
  21#include "qemu/osdep.h"
  22#include "qemu-common.h"
  23#include "qemu/sockets.h"
  24#include "qapi/error.h"
  25#include "socket-helpers.h"
  26#include "monitor/monitor.h"
  27
  28static void test_fd_is_socket_bad(void)
  29{
  30    char *tmp = g_strdup("qemu-test-util-sockets-XXXXXX");
  31    int fd = mkstemp(tmp);
  32    if (fd != 0) {
  33        unlink(tmp);
  34    }
  35    g_free(tmp);
  36
  37    g_assert(fd >= 0);
  38
  39    g_assert(!fd_is_socket(fd));
  40    close(fd);
  41}
  42
  43static void test_fd_is_socket_good(void)
  44{
  45    int fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
  46
  47    g_assert(fd >= 0);
  48
  49    g_assert(fd_is_socket(fd));
  50    close(fd);
  51}
  52
  53static int mon_fd = -1;
  54static const char *mon_fdname;
  55
  56int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
  57{
  58    g_assert(cur_mon);
  59    g_assert(mon == cur_mon);
  60    if (mon_fd == -1 || !g_str_equal(mon_fdname, fdname)) {
  61        error_setg(errp, "No fd named %s", fdname);
  62        return -1;
  63    }
  64    return dup(mon_fd);
  65}
  66
  67/* Syms in libqemustub.a are discarded at .o file granularity.
  68 * To replace monitor_get_fd() we must ensure everything in
  69 * stubs/monitor.c is defined, to make sure monitor.o is discarded
  70 * otherwise we get duplicate syms at link time.
  71 */
  72__thread Monitor *cur_mon;
  73void monitor_init(Chardev *chr, int flags) {}
  74
  75
  76static void test_socket_fd_pass_name_good(void)
  77{
  78    SocketAddress addr;
  79    int fd;
  80
  81    cur_mon = g_malloc(1); /* Fake a monitor */
  82    mon_fdname = "myfd";
  83    mon_fd = qemu_socket(AF_INET, SOCK_STREAM, 0);
  84    g_assert_cmpint(mon_fd, >, STDERR_FILENO);
  85
  86    addr.type = SOCKET_ADDRESS_TYPE_FD;
  87    addr.u.fd.str = g_strdup(mon_fdname);
  88
  89    fd = socket_connect(&addr, &error_abort);
  90    g_assert_cmpint(fd, !=, -1);
  91    g_assert_cmpint(fd, !=, mon_fd);
  92    close(fd);
  93
  94    fd = socket_listen(&addr, &error_abort);
  95    g_assert_cmpint(fd, !=, -1);
  96    g_assert_cmpint(fd, !=, mon_fd);
  97    close(fd);
  98
  99    g_free(addr.u.fd.str);
 100    mon_fdname = NULL;
 101    close(mon_fd);
 102    mon_fd = -1;
 103    g_free(cur_mon);
 104    cur_mon = NULL;
 105}
 106
 107static void test_socket_fd_pass_name_bad(void)
 108{
 109    SocketAddress addr;
 110    Error *err = NULL;
 111    int fd;
 112
 113    cur_mon = g_malloc(1); /* Fake a monitor */
 114    mon_fdname = "myfd";
 115    mon_fd = dup(STDOUT_FILENO);
 116    g_assert_cmpint(mon_fd, >, STDERR_FILENO);
 117
 118    addr.type = SOCKET_ADDRESS_TYPE_FD;
 119    addr.u.fd.str = g_strdup(mon_fdname);
 120
 121    fd = socket_connect(&addr, &err);
 122    g_assert_cmpint(fd, ==, -1);
 123    error_free_or_abort(&err);
 124
 125    fd = socket_listen(&addr, &err);
 126    g_assert_cmpint(fd, ==, -1);
 127    error_free_or_abort(&err);
 128
 129    g_free(addr.u.fd.str);
 130    mon_fdname = NULL;
 131    close(mon_fd);
 132    mon_fd = -1;
 133    g_free(cur_mon);
 134    cur_mon = NULL;
 135}
 136
 137static void test_socket_fd_pass_name_nomon(void)
 138{
 139    SocketAddress addr;
 140    Error *err = NULL;
 141    int fd;
 142
 143    g_assert(cur_mon == NULL);
 144
 145    addr.type = SOCKET_ADDRESS_TYPE_FD;
 146    addr.u.fd.str = g_strdup("myfd");
 147
 148    fd = socket_connect(&addr, &err);
 149    g_assert_cmpint(fd, ==, -1);
 150    error_free_or_abort(&err);
 151
 152    fd = socket_listen(&addr, &err);
 153    g_assert_cmpint(fd, ==, -1);
 154    error_free_or_abort(&err);
 155
 156    g_free(addr.u.fd.str);
 157}
 158
 159
 160static void test_socket_fd_pass_num_good(void)
 161{
 162    SocketAddress addr;
 163    int fd, sfd;
 164
 165    g_assert(cur_mon == NULL);
 166    sfd = qemu_socket(AF_INET, SOCK_STREAM, 0);
 167    g_assert_cmpint(sfd, >, STDERR_FILENO);
 168
 169    addr.type = SOCKET_ADDRESS_TYPE_FD;
 170    addr.u.fd.str = g_strdup_printf("%d", sfd);
 171
 172    fd = socket_connect(&addr, &error_abort);
 173    g_assert_cmpint(fd, ==, sfd);
 174
 175    fd = socket_listen(&addr, &error_abort);
 176    g_assert_cmpint(fd, ==, sfd);
 177
 178    g_free(addr.u.fd.str);
 179    close(sfd);
 180}
 181
 182static void test_socket_fd_pass_num_bad(void)
 183{
 184    SocketAddress addr;
 185    Error *err = NULL;
 186    int fd, sfd;
 187
 188    g_assert(cur_mon == NULL);
 189    sfd = dup(STDOUT_FILENO);
 190
 191    addr.type = SOCKET_ADDRESS_TYPE_FD;
 192    addr.u.fd.str = g_strdup_printf("%d", sfd);
 193
 194    fd = socket_connect(&addr, &err);
 195    g_assert_cmpint(fd, ==, -1);
 196    error_free_or_abort(&err);
 197
 198    fd = socket_listen(&addr, &err);
 199    g_assert_cmpint(fd, ==, -1);
 200    error_free_or_abort(&err);
 201
 202    g_free(addr.u.fd.str);
 203    close(sfd);
 204}
 205
 206static void test_socket_fd_pass_num_nocli(void)
 207{
 208    SocketAddress addr;
 209    Error *err = NULL;
 210    int fd;
 211
 212    cur_mon = g_malloc(1); /* Fake a monitor */
 213
 214    addr.type = SOCKET_ADDRESS_TYPE_FD;
 215    addr.u.fd.str = g_strdup_printf("%d", STDOUT_FILENO);
 216
 217    fd = socket_connect(&addr, &err);
 218    g_assert_cmpint(fd, ==, -1);
 219    error_free_or_abort(&err);
 220
 221    fd = socket_listen(&addr, &err);
 222    g_assert_cmpint(fd, ==, -1);
 223    error_free_or_abort(&err);
 224
 225    g_free(addr.u.fd.str);
 226}
 227
 228
 229int main(int argc, char **argv)
 230{
 231    bool has_ipv4, has_ipv6;
 232
 233    socket_init();
 234
 235    g_test_init(&argc, &argv, NULL);
 236
 237    /* We're creating actual IPv4/6 sockets, so we should
 238     * check if the host running tests actually supports
 239     * each protocol to avoid breaking tests on machines
 240     * with either IPv4 or IPv6 disabled.
 241     */
 242    if (socket_check_protocol_support(&has_ipv4, &has_ipv6) < 0) {
 243        return 1;
 244    }
 245
 246    if (has_ipv4) {
 247        g_test_add_func("/util/socket/is-socket/bad",
 248                        test_fd_is_socket_bad);
 249        g_test_add_func("/util/socket/is-socket/good",
 250                        test_fd_is_socket_good);
 251        g_test_add_func("/socket/fd-pass/name/good",
 252                        test_socket_fd_pass_name_good);
 253        g_test_add_func("/socket/fd-pass/name/bad",
 254                        test_socket_fd_pass_name_bad);
 255        g_test_add_func("/socket/fd-pass/name/nomon",
 256                        test_socket_fd_pass_name_nomon);
 257        g_test_add_func("/socket/fd-pass/num/good",
 258                        test_socket_fd_pass_num_good);
 259        g_test_add_func("/socket/fd-pass/num/bad",
 260                        test_socket_fd_pass_num_bad);
 261        g_test_add_func("/socket/fd-pass/num/nocli",
 262                        test_socket_fd_pass_num_nocli);
 263    }
 264
 265    return g_test_run();
 266}
 267