1df7e0e0dSStefan Hajnoczi // SPDX-License-Identifier: GPL-2.0-only 2df7e0e0dSStefan Hajnoczi /* 3df7e0e0dSStefan Hajnoczi * vsock test utilities 4df7e0e0dSStefan Hajnoczi * 5df7e0e0dSStefan Hajnoczi * Copyright (C) 2017 Red Hat, Inc. 6df7e0e0dSStefan Hajnoczi * 7df7e0e0dSStefan Hajnoczi * Author: Stefan Hajnoczi <stefanha@redhat.com> 8df7e0e0dSStefan Hajnoczi */ 9df7e0e0dSStefan Hajnoczi 10df7e0e0dSStefan Hajnoczi #include <errno.h> 11df7e0e0dSStefan Hajnoczi #include <stdio.h> 12092f32aeSStefan Hajnoczi #include <stdint.h> 13df7e0e0dSStefan Hajnoczi #include <stdlib.h> 14df7e0e0dSStefan Hajnoczi #include <signal.h> 159bb8a29dSStefan Hajnoczi #include <unistd.h> 16770ce007SStefano Garzarella #include <assert.h> 17770ce007SStefano Garzarella #include <sys/epoll.h> 18df7e0e0dSStefan Hajnoczi 19df7e0e0dSStefan Hajnoczi #include "timeout.h" 209bb8a29dSStefan Hajnoczi #include "control.h" 21df7e0e0dSStefan Hajnoczi #include "util.h" 22df7e0e0dSStefan Hajnoczi 23df7e0e0dSStefan Hajnoczi /* Install signal handlers */ 24df7e0e0dSStefan Hajnoczi void init_signals(void) 25df7e0e0dSStefan Hajnoczi { 26df7e0e0dSStefan Hajnoczi struct sigaction act = { 27df7e0e0dSStefan Hajnoczi .sa_handler = sigalrm, 28df7e0e0dSStefan Hajnoczi }; 29df7e0e0dSStefan Hajnoczi 30df7e0e0dSStefan Hajnoczi sigaction(SIGALRM, &act, NULL); 31df7e0e0dSStefan Hajnoczi signal(SIGPIPE, SIG_IGN); 32df7e0e0dSStefan Hajnoczi } 33df7e0e0dSStefan Hajnoczi 34df7e0e0dSStefan Hajnoczi /* Parse a CID in string representation */ 35df7e0e0dSStefan Hajnoczi unsigned int parse_cid(const char *str) 36df7e0e0dSStefan Hajnoczi { 37df7e0e0dSStefan Hajnoczi char *endptr = NULL; 38df7e0e0dSStefan Hajnoczi unsigned long n; 39df7e0e0dSStefan Hajnoczi 40df7e0e0dSStefan Hajnoczi errno = 0; 41df7e0e0dSStefan Hajnoczi n = strtoul(str, &endptr, 10); 42df7e0e0dSStefan Hajnoczi if (errno || *endptr != '\0') { 43df7e0e0dSStefan Hajnoczi fprintf(stderr, "malformed CID \"%s\"\n", str); 44df7e0e0dSStefan Hajnoczi exit(EXIT_FAILURE); 45df7e0e0dSStefan Hajnoczi } 46df7e0e0dSStefan Hajnoczi return n; 47df7e0e0dSStefan Hajnoczi } 48df7e0e0dSStefan Hajnoczi 49770ce007SStefano Garzarella /* Wait for the remote to close the connection */ 50770ce007SStefano Garzarella void vsock_wait_remote_close(int fd) 51770ce007SStefano Garzarella { 52770ce007SStefano Garzarella struct epoll_event ev; 53770ce007SStefano Garzarella int epollfd, nfds; 54770ce007SStefano Garzarella 55770ce007SStefano Garzarella epollfd = epoll_create1(0); 56770ce007SStefano Garzarella if (epollfd == -1) { 57770ce007SStefano Garzarella perror("epoll_create1"); 58770ce007SStefano Garzarella exit(EXIT_FAILURE); 59770ce007SStefano Garzarella } 60770ce007SStefano Garzarella 61770ce007SStefano Garzarella ev.events = EPOLLRDHUP | EPOLLHUP; 62770ce007SStefano Garzarella ev.data.fd = fd; 63770ce007SStefano Garzarella if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) { 64770ce007SStefano Garzarella perror("epoll_ctl"); 65770ce007SStefano Garzarella exit(EXIT_FAILURE); 66770ce007SStefano Garzarella } 67770ce007SStefano Garzarella 68770ce007SStefano Garzarella nfds = epoll_wait(epollfd, &ev, 1, TIMEOUT * 1000); 69770ce007SStefano Garzarella if (nfds == -1) { 70770ce007SStefano Garzarella perror("epoll_wait"); 71770ce007SStefano Garzarella exit(EXIT_FAILURE); 72770ce007SStefano Garzarella } 73770ce007SStefano Garzarella 74770ce007SStefano Garzarella if (nfds == 0) { 75770ce007SStefano Garzarella fprintf(stderr, "epoll_wait timed out\n"); 76770ce007SStefano Garzarella exit(EXIT_FAILURE); 77770ce007SStefano Garzarella } 78770ce007SStefano Garzarella 79770ce007SStefano Garzarella assert(nfds == 1); 80770ce007SStefano Garzarella assert(ev.events & (EPOLLRDHUP | EPOLLHUP)); 81770ce007SStefano Garzarella assert(ev.data.fd == fd); 82770ce007SStefano Garzarella 83770ce007SStefano Garzarella close(epollfd); 84770ce007SStefano Garzarella } 85770ce007SStefano Garzarella 869bb8a29dSStefan Hajnoczi /* Connect to <cid, port> and return the file descriptor. */ 879bb8a29dSStefan Hajnoczi int vsock_stream_connect(unsigned int cid, unsigned int port) 889bb8a29dSStefan Hajnoczi { 899bb8a29dSStefan Hajnoczi union { 909bb8a29dSStefan Hajnoczi struct sockaddr sa; 919bb8a29dSStefan Hajnoczi struct sockaddr_vm svm; 929bb8a29dSStefan Hajnoczi } addr = { 939bb8a29dSStefan Hajnoczi .svm = { 949bb8a29dSStefan Hajnoczi .svm_family = AF_VSOCK, 959bb8a29dSStefan Hajnoczi .svm_port = port, 969bb8a29dSStefan Hajnoczi .svm_cid = cid, 979bb8a29dSStefan Hajnoczi }, 989bb8a29dSStefan Hajnoczi }; 999bb8a29dSStefan Hajnoczi int ret; 1009bb8a29dSStefan Hajnoczi int fd; 1019bb8a29dSStefan Hajnoczi 1029bb8a29dSStefan Hajnoczi control_expectln("LISTENING"); 1039bb8a29dSStefan Hajnoczi 1049bb8a29dSStefan Hajnoczi fd = socket(AF_VSOCK, SOCK_STREAM, 0); 1059bb8a29dSStefan Hajnoczi 1069bb8a29dSStefan Hajnoczi timeout_begin(TIMEOUT); 1079bb8a29dSStefan Hajnoczi do { 1089bb8a29dSStefan Hajnoczi ret = connect(fd, &addr.sa, sizeof(addr.svm)); 1099bb8a29dSStefan Hajnoczi timeout_check("connect"); 1109bb8a29dSStefan Hajnoczi } while (ret < 0 && errno == EINTR); 1119bb8a29dSStefan Hajnoczi timeout_end(); 1129bb8a29dSStefan Hajnoczi 1139bb8a29dSStefan Hajnoczi if (ret < 0) { 1149bb8a29dSStefan Hajnoczi int old_errno = errno; 1159bb8a29dSStefan Hajnoczi 1169bb8a29dSStefan Hajnoczi close(fd); 1179bb8a29dSStefan Hajnoczi fd = -1; 1189bb8a29dSStefan Hajnoczi errno = old_errno; 1199bb8a29dSStefan Hajnoczi } 1209bb8a29dSStefan Hajnoczi return fd; 1219bb8a29dSStefan Hajnoczi } 1229bb8a29dSStefan Hajnoczi 1239bb8a29dSStefan Hajnoczi /* Listen on <cid, port> and return the first incoming connection. The remote 1249bb8a29dSStefan Hajnoczi * address is stored to clientaddrp. clientaddrp may be NULL. 1259bb8a29dSStefan Hajnoczi */ 1269bb8a29dSStefan Hajnoczi int vsock_stream_accept(unsigned int cid, unsigned int port, 1279bb8a29dSStefan Hajnoczi struct sockaddr_vm *clientaddrp) 1289bb8a29dSStefan Hajnoczi { 1299bb8a29dSStefan Hajnoczi union { 1309bb8a29dSStefan Hajnoczi struct sockaddr sa; 1319bb8a29dSStefan Hajnoczi struct sockaddr_vm svm; 1329bb8a29dSStefan Hajnoczi } addr = { 1339bb8a29dSStefan Hajnoczi .svm = { 1349bb8a29dSStefan Hajnoczi .svm_family = AF_VSOCK, 1359bb8a29dSStefan Hajnoczi .svm_port = port, 1369bb8a29dSStefan Hajnoczi .svm_cid = cid, 1379bb8a29dSStefan Hajnoczi }, 1389bb8a29dSStefan Hajnoczi }; 1399bb8a29dSStefan Hajnoczi union { 1409bb8a29dSStefan Hajnoczi struct sockaddr sa; 1419bb8a29dSStefan Hajnoczi struct sockaddr_vm svm; 1429bb8a29dSStefan Hajnoczi } clientaddr; 1439bb8a29dSStefan Hajnoczi socklen_t clientaddr_len = sizeof(clientaddr.svm); 1449bb8a29dSStefan Hajnoczi int fd; 1459bb8a29dSStefan Hajnoczi int client_fd; 1469bb8a29dSStefan Hajnoczi int old_errno; 1479bb8a29dSStefan Hajnoczi 1489bb8a29dSStefan Hajnoczi fd = socket(AF_VSOCK, SOCK_STREAM, 0); 1499bb8a29dSStefan Hajnoczi 1509bb8a29dSStefan Hajnoczi if (bind(fd, &addr.sa, sizeof(addr.svm)) < 0) { 1519bb8a29dSStefan Hajnoczi perror("bind"); 1529bb8a29dSStefan Hajnoczi exit(EXIT_FAILURE); 1539bb8a29dSStefan Hajnoczi } 1549bb8a29dSStefan Hajnoczi 1559bb8a29dSStefan Hajnoczi if (listen(fd, 1) < 0) { 1569bb8a29dSStefan Hajnoczi perror("listen"); 1579bb8a29dSStefan Hajnoczi exit(EXIT_FAILURE); 1589bb8a29dSStefan Hajnoczi } 1599bb8a29dSStefan Hajnoczi 1609bb8a29dSStefan Hajnoczi control_writeln("LISTENING"); 1619bb8a29dSStefan Hajnoczi 1629bb8a29dSStefan Hajnoczi timeout_begin(TIMEOUT); 1639bb8a29dSStefan Hajnoczi do { 1649bb8a29dSStefan Hajnoczi client_fd = accept(fd, &clientaddr.sa, &clientaddr_len); 1659bb8a29dSStefan Hajnoczi timeout_check("accept"); 1669bb8a29dSStefan Hajnoczi } while (client_fd < 0 && errno == EINTR); 1679bb8a29dSStefan Hajnoczi timeout_end(); 1689bb8a29dSStefan Hajnoczi 1699bb8a29dSStefan Hajnoczi old_errno = errno; 1709bb8a29dSStefan Hajnoczi close(fd); 1719bb8a29dSStefan Hajnoczi errno = old_errno; 1729bb8a29dSStefan Hajnoczi 1739bb8a29dSStefan Hajnoczi if (client_fd < 0) 1749bb8a29dSStefan Hajnoczi return client_fd; 1759bb8a29dSStefan Hajnoczi 1769bb8a29dSStefan Hajnoczi if (clientaddr_len != sizeof(clientaddr.svm)) { 1779bb8a29dSStefan Hajnoczi fprintf(stderr, "unexpected addrlen from accept(2), %zu\n", 1789bb8a29dSStefan Hajnoczi (size_t)clientaddr_len); 1799bb8a29dSStefan Hajnoczi exit(EXIT_FAILURE); 1809bb8a29dSStefan Hajnoczi } 1819bb8a29dSStefan Hajnoczi if (clientaddr.sa.sa_family != AF_VSOCK) { 1829bb8a29dSStefan Hajnoczi fprintf(stderr, "expected AF_VSOCK from accept(2), got %d\n", 1839bb8a29dSStefan Hajnoczi clientaddr.sa.sa_family); 1849bb8a29dSStefan Hajnoczi exit(EXIT_FAILURE); 1859bb8a29dSStefan Hajnoczi } 1869bb8a29dSStefan Hajnoczi 1879bb8a29dSStefan Hajnoczi if (clientaddrp) 1889bb8a29dSStefan Hajnoczi *clientaddrp = clientaddr.svm; 1899bb8a29dSStefan Hajnoczi return client_fd; 1909bb8a29dSStefan Hajnoczi } 1919bb8a29dSStefan Hajnoczi 192092f32aeSStefan Hajnoczi /* Transmit one byte and check the return value. 193092f32aeSStefan Hajnoczi * 194092f32aeSStefan Hajnoczi * expected_ret: 195092f32aeSStefan Hajnoczi * <0 Negative errno (for testing errors) 196092f32aeSStefan Hajnoczi * 0 End-of-file 197092f32aeSStefan Hajnoczi * 1 Success 198092f32aeSStefan Hajnoczi */ 199092f32aeSStefan Hajnoczi void send_byte(int fd, int expected_ret, int flags) 200092f32aeSStefan Hajnoczi { 201092f32aeSStefan Hajnoczi const uint8_t byte = 'A'; 202092f32aeSStefan Hajnoczi ssize_t nwritten; 203092f32aeSStefan Hajnoczi 204092f32aeSStefan Hajnoczi timeout_begin(TIMEOUT); 205092f32aeSStefan Hajnoczi do { 206092f32aeSStefan Hajnoczi nwritten = send(fd, &byte, sizeof(byte), flags); 207092f32aeSStefan Hajnoczi timeout_check("write"); 208092f32aeSStefan Hajnoczi } while (nwritten < 0 && errno == EINTR); 209092f32aeSStefan Hajnoczi timeout_end(); 210092f32aeSStefan Hajnoczi 211092f32aeSStefan Hajnoczi if (expected_ret < 0) { 212092f32aeSStefan Hajnoczi if (nwritten != -1) { 213092f32aeSStefan Hajnoczi fprintf(stderr, "bogus send(2) return value %zd\n", 214092f32aeSStefan Hajnoczi nwritten); 215092f32aeSStefan Hajnoczi exit(EXIT_FAILURE); 216092f32aeSStefan Hajnoczi } 217092f32aeSStefan Hajnoczi if (errno != -expected_ret) { 218092f32aeSStefan Hajnoczi perror("write"); 219092f32aeSStefan Hajnoczi exit(EXIT_FAILURE); 220092f32aeSStefan Hajnoczi } 221092f32aeSStefan Hajnoczi return; 222092f32aeSStefan Hajnoczi } 223092f32aeSStefan Hajnoczi 224092f32aeSStefan Hajnoczi if (nwritten < 0) { 225092f32aeSStefan Hajnoczi perror("write"); 226092f32aeSStefan Hajnoczi exit(EXIT_FAILURE); 227092f32aeSStefan Hajnoczi } 228092f32aeSStefan Hajnoczi if (nwritten == 0) { 229092f32aeSStefan Hajnoczi if (expected_ret == 0) 230092f32aeSStefan Hajnoczi return; 231092f32aeSStefan Hajnoczi 232092f32aeSStefan Hajnoczi fprintf(stderr, "unexpected EOF while sending byte\n"); 233092f32aeSStefan Hajnoczi exit(EXIT_FAILURE); 234092f32aeSStefan Hajnoczi } 235092f32aeSStefan Hajnoczi if (nwritten != sizeof(byte)) { 236092f32aeSStefan Hajnoczi fprintf(stderr, "bogus send(2) return value %zd\n", nwritten); 237092f32aeSStefan Hajnoczi exit(EXIT_FAILURE); 238092f32aeSStefan Hajnoczi } 239092f32aeSStefan Hajnoczi } 240092f32aeSStefan Hajnoczi 241092f32aeSStefan Hajnoczi /* Receive one byte and check the return value. 242092f32aeSStefan Hajnoczi * 243092f32aeSStefan Hajnoczi * expected_ret: 244092f32aeSStefan Hajnoczi * <0 Negative errno (for testing errors) 245092f32aeSStefan Hajnoczi * 0 End-of-file 246092f32aeSStefan Hajnoczi * 1 Success 247092f32aeSStefan Hajnoczi */ 248092f32aeSStefan Hajnoczi void recv_byte(int fd, int expected_ret, int flags) 249092f32aeSStefan Hajnoczi { 250092f32aeSStefan Hajnoczi uint8_t byte; 251092f32aeSStefan Hajnoczi ssize_t nread; 252092f32aeSStefan Hajnoczi 253092f32aeSStefan Hajnoczi timeout_begin(TIMEOUT); 254092f32aeSStefan Hajnoczi do { 255092f32aeSStefan Hajnoczi nread = recv(fd, &byte, sizeof(byte), flags); 256092f32aeSStefan Hajnoczi timeout_check("read"); 257092f32aeSStefan Hajnoczi } while (nread < 0 && errno == EINTR); 258092f32aeSStefan Hajnoczi timeout_end(); 259092f32aeSStefan Hajnoczi 260092f32aeSStefan Hajnoczi if (expected_ret < 0) { 261092f32aeSStefan Hajnoczi if (nread != -1) { 262092f32aeSStefan Hajnoczi fprintf(stderr, "bogus recv(2) return value %zd\n", 263092f32aeSStefan Hajnoczi nread); 264092f32aeSStefan Hajnoczi exit(EXIT_FAILURE); 265092f32aeSStefan Hajnoczi } 266092f32aeSStefan Hajnoczi if (errno != -expected_ret) { 267092f32aeSStefan Hajnoczi perror("read"); 268092f32aeSStefan Hajnoczi exit(EXIT_FAILURE); 269092f32aeSStefan Hajnoczi } 270092f32aeSStefan Hajnoczi return; 271092f32aeSStefan Hajnoczi } 272092f32aeSStefan Hajnoczi 273092f32aeSStefan Hajnoczi if (nread < 0) { 274092f32aeSStefan Hajnoczi perror("read"); 275092f32aeSStefan Hajnoczi exit(EXIT_FAILURE); 276092f32aeSStefan Hajnoczi } 277092f32aeSStefan Hajnoczi if (nread == 0) { 278092f32aeSStefan Hajnoczi if (expected_ret == 0) 279092f32aeSStefan Hajnoczi return; 280092f32aeSStefan Hajnoczi 281092f32aeSStefan Hajnoczi fprintf(stderr, "unexpected EOF while receiving byte\n"); 282092f32aeSStefan Hajnoczi exit(EXIT_FAILURE); 283092f32aeSStefan Hajnoczi } 284092f32aeSStefan Hajnoczi if (nread != sizeof(byte)) { 285092f32aeSStefan Hajnoczi fprintf(stderr, "bogus recv(2) return value %zd\n", nread); 286092f32aeSStefan Hajnoczi exit(EXIT_FAILURE); 287092f32aeSStefan Hajnoczi } 288092f32aeSStefan Hajnoczi if (byte != 'A') { 289092f32aeSStefan Hajnoczi fprintf(stderr, "unexpected byte read %c\n", byte); 290092f32aeSStefan Hajnoczi exit(EXIT_FAILURE); 291092f32aeSStefan Hajnoczi } 292092f32aeSStefan Hajnoczi } 293092f32aeSStefan Hajnoczi 294df7e0e0dSStefan Hajnoczi /* Run test cases. The program terminates if a failure occurs. */ 295df7e0e0dSStefan Hajnoczi void run_tests(const struct test_case *test_cases, 296df7e0e0dSStefan Hajnoczi const struct test_opts *opts) 297df7e0e0dSStefan Hajnoczi { 298df7e0e0dSStefan Hajnoczi int i; 299df7e0e0dSStefan Hajnoczi 300df7e0e0dSStefan Hajnoczi for (i = 0; test_cases[i].name; i++) { 301df7e0e0dSStefan Hajnoczi void (*run)(const struct test_opts *opts); 3025a2b2425SStefano Garzarella char *line; 303df7e0e0dSStefan Hajnoczi 3045a2b2425SStefano Garzarella printf("%d - %s...", i, test_cases[i].name); 305df7e0e0dSStefan Hajnoczi fflush(stdout); 306df7e0e0dSStefan Hajnoczi 3072f65b44eSStefan Hajnoczi /* Full barrier before executing the next test. This 3082f65b44eSStefan Hajnoczi * ensures that client and server are executing the 3092f65b44eSStefan Hajnoczi * same test case. In particular, it means whoever is 3102f65b44eSStefan Hajnoczi * faster will not see the peer still executing the 3112f65b44eSStefan Hajnoczi * last test. This is important because port numbers 3122f65b44eSStefan Hajnoczi * can be used by multiple test cases. 3132f65b44eSStefan Hajnoczi */ 3145a2b2425SStefano Garzarella if (test_cases[i].skip) 3155a2b2425SStefano Garzarella control_writeln("SKIP"); 3165a2b2425SStefano Garzarella else 3172f65b44eSStefan Hajnoczi control_writeln("NEXT"); 3182f65b44eSStefan Hajnoczi 3195a2b2425SStefano Garzarella line = control_readln(); 3205a2b2425SStefano Garzarella if (control_cmpln(line, "SKIP", false) || test_cases[i].skip) { 3212f65b44eSStefan Hajnoczi 3225a2b2425SStefano Garzarella printf("skipped\n"); 3235a2b2425SStefano Garzarella 3245a2b2425SStefano Garzarella free(line); 3255a2b2425SStefano Garzarella continue; 3262f65b44eSStefan Hajnoczi } 327df7e0e0dSStefan Hajnoczi 3285a2b2425SStefano Garzarella control_cmpln(line, "NEXT", true); 3295a2b2425SStefano Garzarella free(line); 3305a2b2425SStefano Garzarella 3315a2b2425SStefano Garzarella if (opts->mode == TEST_MODE_CLIENT) 3325a2b2425SStefano Garzarella run = test_cases[i].run_client; 3335a2b2425SStefano Garzarella else 3345a2b2425SStefano Garzarella run = test_cases[i].run_server; 3355a2b2425SStefano Garzarella 336df7e0e0dSStefan Hajnoczi if (run) 337df7e0e0dSStefan Hajnoczi run(opts); 338df7e0e0dSStefan Hajnoczi 339df7e0e0dSStefan Hajnoczi printf("ok\n"); 340df7e0e0dSStefan Hajnoczi } 341df7e0e0dSStefan Hajnoczi } 3425a2b2425SStefano Garzarella 3435a2b2425SStefano Garzarella void list_tests(const struct test_case *test_cases) 3445a2b2425SStefano Garzarella { 3455a2b2425SStefano Garzarella int i; 3465a2b2425SStefano Garzarella 3475a2b2425SStefano Garzarella printf("ID\tTest name\n"); 3485a2b2425SStefano Garzarella 3495a2b2425SStefano Garzarella for (i = 0; test_cases[i].name; i++) 3505a2b2425SStefano Garzarella printf("%d\t%s\n", i, test_cases[i].name); 3515a2b2425SStefano Garzarella 3525a2b2425SStefano Garzarella exit(EXIT_FAILURE); 3535a2b2425SStefano Garzarella } 3545a2b2425SStefano Garzarella 3555a2b2425SStefano Garzarella void skip_test(struct test_case *test_cases, size_t test_cases_len, 3565a2b2425SStefano Garzarella const char *test_id_str) 3575a2b2425SStefano Garzarella { 3585a2b2425SStefano Garzarella unsigned long test_id; 3595a2b2425SStefano Garzarella char *endptr = NULL; 3605a2b2425SStefano Garzarella 3615a2b2425SStefano Garzarella errno = 0; 3625a2b2425SStefano Garzarella test_id = strtoul(test_id_str, &endptr, 10); 3635a2b2425SStefano Garzarella if (errno || *endptr != '\0') { 3645a2b2425SStefano Garzarella fprintf(stderr, "malformed test ID \"%s\"\n", test_id_str); 3655a2b2425SStefano Garzarella exit(EXIT_FAILURE); 3665a2b2425SStefano Garzarella } 3675a2b2425SStefano Garzarella 3685a2b2425SStefano Garzarella if (test_id >= test_cases_len) { 3695a2b2425SStefano Garzarella fprintf(stderr, "test ID (%lu) larger than the max allowed (%lu)\n", 3705a2b2425SStefano Garzarella test_id, test_cases_len - 1); 3715a2b2425SStefano Garzarella exit(EXIT_FAILURE); 3725a2b2425SStefano Garzarella } 3735a2b2425SStefano Garzarella 3745a2b2425SStefano Garzarella test_cases[test_id].skip = true; 3755a2b2425SStefano Garzarella } 376