diff options
Diffstat (limited to 'usr/src/test')
19 files changed, 1864 insertions, 25 deletions
diff --git a/usr/src/test/libc-tests/tests/random/Makefile b/usr/src/test/libc-tests/tests/random/Makefile index ed480dacb9..c1a1a18e1f 100644 --- a/usr/src/test/libc-tests/tests/random/Makefile +++ b/usr/src/test/libc-tests/tests/random/Makefile @@ -17,7 +17,6 @@ include $(SRC)/Makefile.master ROOTOPTPKG = $(ROOT)/opt/libc-tests TESTDIR = $(ROOTOPTPKG)/tests/random -ROOTBINDIR = $(ROOTOPTPKG)/bin PROGS = arc4random \ arc4random_prefork \ @@ -74,17 +73,12 @@ arc4random_preforksig: arc4random_forksig.c $(POST_PROCESS) chacha: chacha_tv.c - $(COMPILE.c) -DKEYSTREAM_ONLY -I$(SRC)/common/crypto/chacha -o chacha.o -c $(SRC)/common/crypto/chacha/chacha.c + $(COMPILE.c) -DKEYSTREAM_ONLY -I$(SRC)/common/crypto/chacha \ + -o chacha.o -c $(SRC)/common/crypto/chacha/chacha.c $(COMPILE.c) -I$(SRC)/common/crypto/chacha -o chacha_tv.o -c chacha_tv.c $(LINK.c) -o $@ chacha_tv.o chacha.o $(LDLIBS) $(POST_PROCESS) -$(ROOTBINDIR): - $(INS.dir) - -$(ROOTBINDIR)/%: % - $(INS.file) - $(TESTDIR): $(INS.dir) diff --git a/usr/src/test/os-tests/tests/Makefile b/usr/src/test/os-tests/tests/Makefile index f3958afd29..cd4104500c 100644 --- a/usr/src/test/os-tests/tests/Makefile +++ b/usr/src/test/os-tests/tests/Makefile @@ -13,6 +13,6 @@ # Copyright (c) 2012 by Delphix. All rights reserved. # -SUBDIRS = poll sigqueue +SUBDIRS = poll sigqueue spoof-ras include $(SRC)/test/Makefile.com diff --git a/usr/src/test/os-tests/tests/spoof-ras/Makefile b/usr/src/test/os-tests/tests/spoof-ras/Makefile new file mode 100644 index 0000000000..c629a03594 --- /dev/null +++ b/usr/src/test/os-tests/tests/spoof-ras/Makefile @@ -0,0 +1,57 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 by Joyent, Inc. All rights reserved. +# + +include $(SRC)/cmd/Makefile.cmd +include $(SRC)/test/Makefile.com + +PROG = spoof-ras +OBJS = $(PROG:%=%.o) +SRCS = $(OBJS:%.o=%.c) + +LDLIBS += -lsocket -lnsl +C99MODE = -xc99=%all + +ROOTOPTPKG = $(ROOT)/opt/os-tests +TESTDIR = $(ROOTOPTPKG)/tests + +CMDS = $(PROG:%=$(TESTDIR)/%) +$(CMDS) := FILEMODE = 0555 + +all: $(PROG) + +$(PROG): $(OBJS) + $(LINK.c) $(OBJS) -o $@ $(LDLIBS) + $(POST_PROCESS) + +%.o: ../%.c + $(COMPILE.c) $< + +install: all $(CMDS) + +lint: lint_SRCS + +clobber: clean + -$(RM) $(PROG) + +clean: + -$(RM) $(OBJS) + +$(CMDS): $(TESTDIR) $(PROG) + +$(TESTDIR): + $(INS.dir) + +$(TESTDIR)/%: % + $(INS.file) diff --git a/usr/src/test/os-tests/tests/spoof-ras/spoof-ras.c b/usr/src/test/os-tests/tests/spoof-ras/spoof-ras.c new file mode 100644 index 0000000000..23a5e11c0c --- /dev/null +++ b/usr/src/test/os-tests/tests/spoof-ras/spoof-ras.c @@ -0,0 +1,683 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2015 Joyent, Inc. All rights reserved. + */ + +#include <strings.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <err.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/sockio.h> +#include <sys/wait.h> +#include <unistd.h> +#include <signal.h> +#include <netinet/in_systm.h> /* legacy network types needed by ip_icmp.h */ +#include <netinet/in.h> +#include <netinet/ip.h> +#include <netinet/ip6.h> +#include <netinet/ip_icmp.h> +#include <netinet/icmp6.h> +#include <net/if.h> +#include <arpa/inet.h> +#include <priv.h> + +/* + * This program is meant to test the behaviour of processing incoming Router + * Advertisements when IP spoofing protection (ip-nospoof) is enabled. When + * run, it creates an etherstub on which it places two VNICs: a source VNIC, + * and a destination VNIC with protection enabled. It then sends out spoofed + * Router Advertisements with varying incorrect values. + * + * IMPORTANT: These tests expect that there is no other IPv6 traffic on the + * machine that would be delivered to a VNIC with spoofing protection enabled, + * since this would trip the DTrace probes installed by this suite of tests. + * Care should therefore be taken to not run it as a part of any series of + * tests which may be executed in such an environment, as it could lead to + * spurious failures. + */ + +#define DLADM(args...) spoof_run_proc("/usr/sbin/dladm", \ + (char *[]) { "dladm", args, NULL }) +#define IFCONFIG(args...) spoof_run_proc("/usr/sbin/ifconfig", \ + (char *[]) { "ifconfig", args, NULL }) + +typedef struct sockaddr_in6 sin6_t; +typedef int (spoof_test_f)(int, struct lif_nd_req *, sin6_t *); + +/* + * Get the link-layer address of the given interface by querying + * the neighbour cache. + */ +static int +spoof_get_lla(int s, const char *iface, struct lifreq *addrp, + struct lifreq *llap) +{ + if (strstr(iface, ":")) { + warnx("Specified interface should be the zeroth " + "logical interface on the physical device."); + } + + bzero(addrp, sizeof (*addrp)); + bzero(llap, sizeof (*llap)); + + (void) strlcpy(addrp->lifr_name, iface, LIFNAMSIZ); + if (ioctl(s, SIOCGLIFADDR, addrp) < 0) { + warn("Unable to get link-local address"); + return (-1); + } + + (void) strlcpy(llap->lifr_name, iface, LIFNAMSIZ); + bcopy(&addrp->lifr_addr, &llap->lifr_nd.lnr_addr, + sizeof (struct sockaddr_storage)); + + if (ioctl(s, SIOCLIFGETND, llap) < 0) { + warn("Failed to get link-layer address"); + return (-1); + } + + return (0); +} + +static void +spoof_prepare_lla(struct nd_opt_lla *llap, struct lif_nd_req *nce, + struct iovec *iov) +{ + uint_t optlen; + + bzero(llap, sizeof (*llap)); + llap->nd_opt_lla_type = ND_OPT_SOURCE_LINKADDR; + optlen = ((sizeof (struct nd_opt_hdr) + + nce->lnr_hdw_len + 7) / 8) * 8; + llap->nd_opt_lla_len = optlen / 8; + bcopy(&nce->lnr_hdw_addr, + &llap->nd_opt_lla_hdw_addr, nce->lnr_hdw_len); + + iov->iov_base = (caddr_t)llap; + iov->iov_len = optlen; +} + +static void +spoof_prepare_pi(const char *prefix, int prefix_len, + struct nd_opt_prefix_info *pip, struct iovec *iov) +{ + bzero(pip, sizeof (*pip)); + + pip->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; + pip->nd_opt_pi_len = 4; + pip->nd_opt_pi_prefix_len = prefix_len; + pip->nd_opt_pi_flags_reserved = + ND_OPT_PI_FLAG_AUTO | ND_OPT_PI_FLAG_ONLINK; + pip->nd_opt_pi_valid_time = 86400; + pip->nd_opt_pi_preferred_time = 86400; + if (inet_pton(AF_INET6, prefix, &pip->nd_opt_pi_prefix) == 0) { + errx(EXIT_FAILURE, "The prefix \"%s\" is " + "not a valid input prefix", prefix); + } + + iov->iov_base = (caddr_t)pip; + iov->iov_len = sizeof (*pip); +} + +static void +spoof_prepare_header(struct nd_router_advert *ichdrp, struct iovec *iov) +{ + bzero(ichdrp, sizeof (*ichdrp)); + + ichdrp->nd_ra_type = ND_ROUTER_ADVERT; + ichdrp->nd_ra_curhoplimit = 255; + + iov->iov_base = (caddr_t)ichdrp; + iov->iov_len = sizeof (*ichdrp); +} + +static int +spoof_set_max_hops(int s) +{ + int ttl = 255; + + if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, + (char *)&ttl, sizeof (ttl)) < 0) { + warn("Failed to set IPV6_UNICAST_HOPS socket option"); + return (-1); + } + if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, + (char *)&ttl, sizeof (ttl)) < 0) { + warn("Failed to set IPV6_UNICAST_HOPS socket option"); + return (-1); + } + + return (0); +} + +/* + * Send bad option lengths in the Link-Layer Source Address option + */ +static int +spoof_bad_lla_optlen_test(int s, struct lif_nd_req *nce, sin6_t *multicast) +{ + struct msghdr msg6; + struct iovec iovs[3]; + struct nd_router_advert ichdr; + struct nd_opt_lla lla; + struct nd_opt_prefix_info pi; + uint8_t old_lla_len; + + spoof_prepare_header(&ichdr, &iovs[0]); + spoof_prepare_lla(&lla, nce, &iovs[1]); + spoof_prepare_pi("fd00::", 64, &pi, &iovs[2]); + + /* Prepare message */ + bzero(&msg6, sizeof (struct msghdr)); + msg6.msg_name = multicast; + msg6.msg_namelen = sizeof (sin6_t); + msg6.msg_iov = iovs; + msg6.msg_iovlen = 3; + + old_lla_len = lla.nd_opt_lla_len; + + + /* + * Length is now smaller than the option is, so this should + * be rejected. + */ + lla.nd_opt_lla_len = 0; + if (sendmsg(s, &msg6, 0) < 0) { + warn("Failed to send ICMPv6 message"); + return (-1); + } + + /* + * Length is bigger than the option, so the following prefix + * will be offset. + */ + lla.nd_opt_lla_len = 2; + if (sendmsg(s, &msg6, 0) < 0) { + warn("Failed to send ICMPv6 message"); + return (-1); + } + + /* + * Restore the length, but shorten the amount of data to send, so we're + * sending truncated packets. (Stop before 0, so that we still send part + * of the option.) + */ + lla.nd_opt_lla_len = old_lla_len; + for (iovs[1].iov_len--; iovs[1].iov_len > 0; iovs[1].iov_len--) { + if (sendmsg(s, &msg6, 0) < 0) { + warn("Failed to send ICMPv6 message"); + return (-1); + } + } + + return (0); +} + +/* + * Send bad option lengths in the Prefix Information option + */ +static int +spoof_bad_pi_optlen_test(int s, struct lif_nd_req *nce, sin6_t *multicast) +{ + struct msghdr msg6; + struct iovec iovs[3]; + struct nd_router_advert ichdr; + struct nd_opt_lla lla; + struct nd_opt_prefix_info pi; + uint8_t old_pi_len; + + spoof_prepare_header(&ichdr, &iovs[0]); + spoof_prepare_lla(&lla, nce, &iovs[1]); + spoof_prepare_pi("fd00::", 64, &pi, &iovs[2]); + + /* Prepare message */ + bzero(&msg6, sizeof (struct msghdr)); + msg6.msg_name = multicast; + msg6.msg_namelen = sizeof (sin6_t); + msg6.msg_iov = iovs; + msg6.msg_iovlen = 3; + + old_pi_len = pi.nd_opt_pi_len; + + /* + * Length is now smaller than the option is, so this should + * be rejected. + */ + pi.nd_opt_pi_len = 0; + if (sendmsg(s, &msg6, 0) < 0) { + warn("Failed to send ICMPv6 message"); + return (-1); + } + + /* + * Length is smaller than a PI option should be. + */ + pi.nd_opt_pi_len = 3; + if (sendmsg(s, &msg6, 0) < 0) { + warn("Failed to send ICMPv6 message"); + return (-1); + } + + /* + * Length is bigger than the option, so the following prefix + * will be offset. + */ + pi.nd_opt_pi_len = 5; + if (sendmsg(s, &msg6, 0) < 0) { + warn("Failed to send ICMPv6 message"); + return (-1); + } + + /* + * Restore the length, but shorten the amount of data to send, so we're + * sending truncated packets. (Stop before 0, so that we still send part + * of the option.) + */ + pi.nd_opt_pi_len = old_pi_len; + for (iovs[2].iov_len--; iovs[2].iov_len > 0; iovs[2].iov_len--) { + if (sendmsg(s, &msg6, 0) < 0) { + warn("Failed to send ICMPv6 message"); + return (-1); + } + } + + return (0); +} + +/* + * Advertise a prefix with a prefix length greater than 128. + */ +static int +spoof_bad_plen_test(int s, struct lif_nd_req *nce, sin6_t *multicast) +{ + struct msghdr msg6; + struct iovec iovs[3]; + struct nd_router_advert ichdr; + struct nd_opt_lla lla; + struct nd_opt_prefix_info pi; + + spoof_prepare_header(&ichdr, &iovs[0]); + spoof_prepare_lla(&lla, nce, &iovs[1]); + spoof_prepare_pi("fd00::", 130, &pi, &iovs[2]); + + /* Prepare message */ + bzero(&msg6, sizeof (struct msghdr)); + msg6.msg_name = multicast; + msg6.msg_namelen = sizeof (sin6_t); + msg6.msg_iov = iovs; + msg6.msg_iovlen = 3; + + if (sendmsg(s, &msg6, 0) < 0) { + warn("Failed to send ICMPv6 message"); + return (-1); + } + + return (0); +} + +/* + * Advertise a link-local prefix, which should be disallowed and ignored. + */ +static int +spoof_link_local_test(int s, struct lif_nd_req *nce, sin6_t *multicast) +{ + struct msghdr msg6; + struct iovec iovs[3]; + struct nd_router_advert ichdr; + struct nd_opt_lla lla; + struct nd_opt_prefix_info pi; + + spoof_prepare_header(&ichdr, &iovs[0]); + spoof_prepare_lla(&lla, nce, &iovs[1]); + spoof_prepare_pi("fe80::", 64, &pi, &iovs[2]); + + /* Prepare message */ + bzero(&msg6, sizeof (struct msghdr)); + msg6.msg_name = multicast; + msg6.msg_namelen = sizeof (sin6_t); + msg6.msg_iov = iovs; + msg6.msg_iovlen = 3; + + if (sendmsg(s, &msg6, 0) < 0) { + warn("Failed to send ICMPv6 message"); + return (-1); + } + + return (0); +} + +static int +spoof_good_test(int s, struct lif_nd_req *nce, sin6_t *multicast) +{ + struct msghdr msg6; + struct iovec iovs[3]; + struct nd_router_advert ichdr; + struct nd_opt_lla lla; + struct nd_opt_prefix_info pi; + + spoof_prepare_header(&ichdr, &iovs[0]); + spoof_prepare_lla(&lla, nce, &iovs[1]); + spoof_prepare_pi("fd00::", 64, &pi, &iovs[2]); + + /* Prepare message */ + bzero(&msg6, sizeof (struct msghdr)); + msg6.msg_name = multicast; + msg6.msg_namelen = sizeof (sin6_t); + msg6.msg_iov = iovs; + msg6.msg_iovlen = 3; + + if (sendmsg(s, &msg6, 0) < 0) { + warn("Failed to send ICMPv6 message"); + return (-1); + } + + return (0); +} + +static spoof_test_f *test_cases[] = { + spoof_bad_lla_optlen_test, + spoof_bad_pi_optlen_test, + spoof_bad_plen_test, + spoof_link_local_test +}; + +static int test_cases_count = sizeof (test_cases) / sizeof (spoof_test_f *); + +static pid_t +spoof_dtrace_launch(void) +{ + pid_t child_pid = fork(); + if (child_pid == (pid_t)-1) { + err(EXIT_FAILURE, "Failed to fork to execute dtrace"); + } else if (child_pid == (pid_t)0) { + (void) execl("/usr/sbin/dtrace", "dtrace", "-q", + "-n", "sdt:mac:insert_slaac_ip:generated-addr { exit(10) }", + NULL); + err(EXIT_FAILURE, "Failed to execute dtrace"); + } + + return (child_pid); +} + +static pid_t +spoof_dtrace_wait(pid_t dtrace, int *stat) +{ + int retpid; + + /* Give time for probe to fire before checking status */ + (void) sleep(5); + + while ((retpid = waitpid(dtrace, stat, WNOHANG)) == -1) { + if (errno == EINTR) + continue; + + err(EXIT_FAILURE, "Failed to wait on child"); + } + + return (retpid); +} + +/* + * Run a function that's going to exec in a child process, and don't return + * until it exits. + */ +static int +spoof_run_proc(char *path, char *args[]) +{ + pid_t child_pid; + int childstat = 0, status = 0; + + child_pid = fork(); + if (child_pid == (pid_t)-1) { + err(EXIT_FAILURE, "Unable to fork to execute %s", path); + } else if (child_pid == (pid_t)0) { + (void) execv(path, args); + err(EXIT_FAILURE, "Failed to execute %s", path); + } + + while (waitpid(child_pid, &childstat, 0) == -1) { + if (errno == EINTR) + continue; + + warn("Failed to wait on child"); + return (-1); + } + + status = WEXITSTATUS(childstat); + if (status != 0) { + warnx("Child process %s exited with %d", path, status); + return (-1); + } + + return (0); +} + +static void +spoof_network_teardown(char *testether, char *testvnic0, char *testvnic1) +{ + // Delete dest vnic + (void) IFCONFIG(testvnic1, "inet6", "unplumb"); + (void) DLADM("delete-vnic", testvnic1); + + // Delete source vnic + (void) IFCONFIG(testvnic0, "inet6", "unplumb"); + (void) DLADM("delete-vnic", testvnic0); + + // Delete etherstub + (void) DLADM("delete-etherstub", testether); +} + +static int +spoof_network_setup(char *testether, char *testvnic0, char *testvnic1) +{ + // Create etherstub + if (DLADM("create-etherstub", "-t", testether) != 0) { + warnx("Failed to create etherstub for test network"); + return (-1); + } + + // Create source vnic + if (DLADM("create-vnic", "-t", "-l", testether, testvnic0) != 0) { + warnx("Failed to create source VNIC for test network"); + return (-1); + } + + if (IFCONFIG(testvnic0, "inet6", "plumb", "up") != 0) { + warnx("Failed to plumb source VNIC for test network"); + return (-1); + } + + // Create dest vnic + if (DLADM("create-vnic", "-t", "-l", testether, + "-p", "protection=mac-nospoof,restricted,ip-nospoof,dhcp-nospoof", + testvnic1) != 0) { + warnx("Failed to create destination VNIC for test network"); + return (-1); + } + + if (IFCONFIG(testvnic1, "inet6", "plumb", "up") != 0) { + warnx("Failed to plumb destination VNIC for test network"); + return (-1); + } + + return (0); +} + +static void +spoof_run_test(spoof_test_f *func, int s, struct lif_nd_req *nce, + sin6_t *multicast) +{ + static int cas = 1; + (void) printf("Executing test case #%d...", cas++); + if (func(s, nce, multicast) == 0) { + (void) printf(" Done.\n"); + } else { + (void) printf(" Error while running!\n"); + } +} + +static int +spoof_run_tests(int s, struct lif_nd_req *nce) +{ + int cas, stat; + pid_t dtrace; + sin6_t multicast; + + /* Prepare all-nodes multicast address */ + bzero(&multicast, sizeof (multicast)); + multicast.sin6_family = AF_INET6; + (void) inet_pton(AF_INET6, "ff02::1", &multicast.sin6_addr); + + dtrace = spoof_dtrace_launch(); + + /* Wait an adequate amount of time for the probes to be installed */ + (void) sleep(5); + + /* + * We send a packet where everything is good, except for the hop limit. + * This packet should be rejected. + */ + spoof_run_test(spoof_good_test, s, nce, &multicast); + + if (spoof_set_max_hops(s) != 0) { + warnx("Failed to set hop limit on socket"); + return (EXIT_FAILURE); + } + + for (cas = 0; cas < test_cases_count; cas++) { + spoof_run_test(test_cases[cas], s, nce, &multicast); + } + + + if (spoof_dtrace_wait(dtrace, &stat) != 0) { + (void) printf("One or more tests of bad behaviour failed!\n"); + return (EXIT_FAILURE); + } + + /* + * Now that we've executed all of the test cases that should fail, we + * can execute the test that should succeed, to make sure the normal + * case works properly. This should trip the dtrace probe. + */ + spoof_run_test(spoof_good_test, s, nce, &multicast); + + if (spoof_dtrace_wait(dtrace, &stat) != 0 && WIFEXITED(stat) && + WEXITSTATUS(stat) == 10) { + (void) printf("Tests completed successfully!\n"); + } else { + if (kill(dtrace, SIGKILL) != 0) { + warn("Failed to kill dtrace child (pid %d)", dtrace); + } + (void) printf("Test of normal behaviour didn't succeed!\n"); + return (EXIT_FAILURE); + } + + return (0); +} + +/* + * Make sure that we have all of the privileges we need to execute these tests, + * so that we can error out before we would fail. + */ +void +spoof_check_privs(void) +{ + priv_set_t *privset = priv_allocset(); + + if (privset == NULL) { + err(EXIT_FAILURE, "Failed to allocate memory for " + "checking privileges"); + } + + if (getppriv(PRIV_EFFECTIVE, privset) != 0) { + err(EXIT_FAILURE, "Failed to get current privileges"); + } + + if (!priv_ismember(privset, PRIV_DTRACE_KERNEL)) { + errx(EXIT_FAILURE, "These tests need to be run as a user " + "capable of tracing the kernel."); + } + + if (!priv_ismember(privset, PRIV_SYS_NET_CONFIG)) { + errx(EXIT_FAILURE, "These tests need to be run as a user " + "capable of creating and configuring network interfaces."); + } + + if (!priv_ismember(privset, PRIV_NET_ICMPACCESS)) { + errx(EXIT_FAILURE, "These tests need to be run as a user " + "capable of sending ICMP packets."); + } + + priv_freeset(privset); +} + +int +main(void) +{ + struct lifreq addr, llar; + int error, s; + char testether[LIFNAMSIZ]; + char testvnic0[LIFNAMSIZ]; + char testvnic1[LIFNAMSIZ]; + pid_t curpid = getpid(); + + spoof_check_privs(); + + /* + * Set up the socket and test network for sending + */ + s = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6); + if (s < 0) { + err(EXIT_FAILURE, "Failed to open ICMPv6 socket"); + } + + (void) snprintf(testether, sizeof (testether), "testether%d", curpid); + (void) snprintf(testvnic0, sizeof (testvnic0), "testvnic%d_0", curpid); + (void) snprintf(testvnic1, sizeof (testvnic1), "testvnic%d_1", curpid); + + if (spoof_network_setup(testether, testvnic0, testvnic1) != 0) { + warnx("Failed to set up test network"); + error = EXIT_FAILURE; + goto cleanup; + } + + if (spoof_get_lla(s, testvnic0, &addr, &llar) != 0) { + warnx("Failed to get link-layer address"); + error = EXIT_FAILURE; + goto cleanup; + } + + if (setsockopt(s, IPPROTO_IPV6, IPV6_BOUND_IF, + (char *)&((sin6_t *)&addr.lifr_addr)->sin6_scope_id, + sizeof (int)) < 0) { + warn("Failed to set IPV6_UNICAST_HOPS socket option"); + return (-1); + } + + if (bind(s, (struct sockaddr *)&addr.lifr_addr, sizeof (sin6_t)) != 0) { + warnx("Failed to bind to link-local address"); + error = EXIT_FAILURE; + goto cleanup; + } + + error = spoof_run_tests(s, &llar.lifr_nd); + +cleanup: + if (close(s) != 0) { + warnx("Failed to close ICMPv6 socket"); + } + spoof_network_teardown(testether, testvnic0, testvnic1); + return (error); +} diff --git a/usr/src/test/test-runner/cmd/Makefile b/usr/src/test/test-runner/cmd/Makefile index 33e7a61275..948aea9ed8 100644 --- a/usr/src/test/test-runner/cmd/Makefile +++ b/usr/src/test/test-runner/cmd/Makefile @@ -34,4 +34,6 @@ $(ROOTBIN): $(INS.dir) $(ROOTBIN)/%: %.py - $(INS.rename) + $(RM) $@ + $(SED.py) $< > $@ + $(CHMOD) 0555 $@ diff --git a/usr/src/test/test-runner/cmd/run.py b/usr/src/test/test-runner/cmd/run.py index 4fe2e6dc37..c42e2e852e 100644 --- a/usr/src/test/test-runner/cmd/run.py +++ b/usr/src/test/test-runner/cmd/run.py @@ -1,4 +1,4 @@ -#!/usr/bin/python2.6 +#!ON_PYTHON_26 # # This file and its contents are supplied under the terms of the diff --git a/usr/src/test/util-tests/runfiles/default.run b/usr/src/test/util-tests/runfiles/default.run index 3f7498e23b..dcdbf43f95 100644 --- a/usr/src/test/util-tests/runfiles/default.run +++ b/usr/src/test/util-tests/runfiles/default.run @@ -24,9 +24,14 @@ outputdir = /var/tmp/test_results [/opt/util-tests/tests/printf_test] [/opt/util-tests/tests/allowed-ips] +[/opt/util-tests/tests/vnic-mtu] +[/opt/util-tests/tests/bunyan] [/opt/util-tests/tests/xargs_test] +[/opt/util-tests/tests/mqt] +[/opt/util-tests/tests/wqt] + [/opt/util-tests/tests/libnvpair_json] tests = ['json_00_blank', 'json_01_boolean', 'json_02_numbers', 'json_03_empty_arrays', 'json_04_number_arrays', 'json_05_strings', diff --git a/usr/src/test/util-tests/tests/Makefile b/usr/src/test/util-tests/tests/Makefile index 4709c7adcd..739b79893f 100644 --- a/usr/src/test/util-tests/tests/Makefile +++ b/usr/src/test/util-tests/tests/Makefile @@ -14,7 +14,6 @@ # Copyright 2014 Garrett D'Amore <garrett@damore.org> # -SUBDIRS = dladm printf xargs -SUBDIRS = dladm libnvpair_json printf xargs +SUBDIRS = dladm libnvpair_json printf xargs mergeq workq include $(SRC)/test/Makefile.com diff --git a/usr/src/test/util-tests/tests/bunyan/Makefile b/usr/src/test/util-tests/tests/bunyan/Makefile new file mode 100644 index 0000000000..5f58bf1614 --- /dev/null +++ b/usr/src/test/util-tests/tests/bunyan/Makefile @@ -0,0 +1,68 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2015 Joyent, Inc. +# + +include $(SRC)/Makefile.master + +ROOTOPTPKG = $(ROOT)/opt/util-tests +TESTDIR = $(ROOTOPTPKG)/tests/bunyan +TESTBIN = $(ROOTOPTPKG)/bin + +PROG = btest + +SCRIPTS = \ + bunyan + +include $(SRC)/cmd/Makefile.cmd +include $(SRC)/test/Makefile.com + +OBJS = $(PROG:%=%.o) +SRCS = $(OBJS:%.o=%.c) + +CMDS = $(PROG:%=$(TESTBIN)/%) $(SCRIPTS:%=$(TESTDIR)/%) +$(CMDS) := FILEMODE = 0555 + +DIRS = $(TESTDIR) $(TESTBIN) + +LDLIBS += -lbunyan + +all: $(PROG) + +$(PROG): $(OBJS) + $(LINK.c) $(OBJS) -o $@ $(LDLIBS) + $(POST_PROCESS) + +install: all $(CMDS) + +lint: + +clobber: clean + -$(RM) $(PROG) + +clean: + -$(RM) $(OBJS) + +$(CMDS): $(DIRS) + +$(DIRS): + $(INS.dir) + +$(TESTDIR)/%: %.ksh + $(INS.rename) + +$(TESTDIR)/%: % + $(INS.file) + +$(TESTBIN)/%: % + $(INS.file) diff --git a/usr/src/test/util-tests/tests/bunyan/btest.c b/usr/src/test/util-tests/tests/bunyan/btest.c new file mode 100644 index 0000000000..5239e91f1e --- /dev/null +++ b/usr/src/test/util-tests/tests/bunyan/btest.c @@ -0,0 +1,312 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2014, Joyent, Inc. + */ + +#include <stdio.h> +#include <assert.h> +#include <bunyan.h> +#include <netinet/in.h> +#include <strings.h> + +static void +create_handles(void) +{ + bunyan_logger_t *a, *b, *c; + + assert(bunyan_init("foo", &a) == 0); + assert(bunyan_init("foo", &b) == 0); + assert(bunyan_init("foo", &c) == 0); + bunyan_fini(a); + bunyan_fini(b); + bunyan_fini(c); +} + +static void +create_stream(void) +{ + bunyan_logger_t *a; + + assert(bunyan_init("foo", &a) == 0); + assert(bunyan_stream_add(a, "bar", BUNYAN_L_TRACE, + bunyan_stream_fd, (void *)1) == 0); + assert(bunyan_stream_add(a, "baz", BUNYAN_L_TRACE, + bunyan_stream_fd, (void *)1) == 0); + assert(bunyan_stream_add(a, "bar", BUNYAN_L_TRACE, + bunyan_stream_fd, (void *)1) == EEXIST); + assert(bunyan_stream_add(a, "baz", BUNYAN_L_TRACE, + bunyan_stream_fd, (void *)1) == EEXIST); + assert(bunyan_stream_remove(a, "baz") == 0); + assert(bunyan_stream_remove(a, "baz") == ENOENT); + assert(bunyan_stream_remove(a, "foobaz") == ENOENT); + assert(bunyan_stream_remove(a, "blah") == ENOENT); + assert(bunyan_stream_add(a, "bar", BUNYAN_L_TRACE, + bunyan_stream_fd, (void *)1) == EEXIST); + assert(bunyan_stream_add(a, "baz", BUNYAN_L_TRACE, + bunyan_stream_fd, (void *)1) == 0); + assert(bunyan_stream_add(a, "debug", BUNYAN_L_DEBUG, + bunyan_stream_fd, (void *)1) == 0); + assert(bunyan_stream_add(a, "info", BUNYAN_L_INFO, + bunyan_stream_fd, (void *)1) == 0); + assert(bunyan_stream_add(a, "warn", BUNYAN_L_WARN, + bunyan_stream_fd, (void *)1) == 0); + assert(bunyan_stream_add(a, "error", BUNYAN_L_ERROR, + bunyan_stream_fd, (void *)1) == 0); + assert(bunyan_stream_add(a, "fatal", BUNYAN_L_FATAL, + bunyan_stream_fd, (void *)1) == 0); + + bunyan_fini(a); +} + +static void +create_key(void) +{ + bunyan_logger_t *a; + struct in_addr v4; + struct in6_addr v6; + + assert(bunyan_init("foo", &a) == 0); + assert(bunyan_key_remove(a, "blah") == ENOENT); + assert(bunyan_key_add(a, BUNYAN_T_END) == 0); + + assert(bunyan_key_add(a, BUNYAN_T_STRING, "s", "foo", + BUNYAN_T_POINTER, "p", (void *)a, BUNYAN_T_IP, "v4", &v4, + BUNYAN_T_IP6, "v6", &v6, BUNYAN_T_BOOLEAN, "b", B_TRUE, + BUNYAN_T_INT32, "i32", 69, BUNYAN_T_INT64, "i64", (uint64_t)6969, + BUNYAN_T_UINT32, "u32", 23, BUNYAN_T_UINT64, "u64", (uint64_t)2323, + BUNYAN_T_DOUBLE, "d", 3.14, + BUNYAN_T_INT64STR, "i64s", (uint64_t)12345, + BUNYAN_T_UINT64STR, "u64s", (uint64_t)54321, BUNYAN_T_END) == 0); + + assert(bunyan_key_remove(a, "s") == 0); + assert(bunyan_key_remove(a, "s") == ENOENT); + assert(bunyan_key_remove(a, "p") == 0); + assert(bunyan_key_remove(a, "p") == ENOENT); + assert(bunyan_key_remove(a, "v4") == 0); + assert(bunyan_key_remove(a, "v4") == ENOENT); + assert(bunyan_key_remove(a, "v6") == 0); + assert(bunyan_key_remove(a, "v6") == ENOENT); + assert(bunyan_key_remove(a, "b") == 0); + assert(bunyan_key_remove(a, "b") == ENOENT); + assert(bunyan_key_remove(a, "i32") == 0); + assert(bunyan_key_remove(a, "i32") == ENOENT); + assert(bunyan_key_remove(a, "i64") == 0); + assert(bunyan_key_remove(a, "i64") == ENOENT); + assert(bunyan_key_remove(a, "u32") == 0); + assert(bunyan_key_remove(a, "u32") == ENOENT); + assert(bunyan_key_remove(a, "u64") == 0); + assert(bunyan_key_remove(a, "u64") == ENOENT); + assert(bunyan_key_remove(a, "d") == 0); + assert(bunyan_key_remove(a, "d") == ENOENT); + assert(bunyan_key_remove(a, "i64s") == 0); + assert(bunyan_key_remove(a, "i64s") == ENOENT); + assert(bunyan_key_remove(a, "u64s") == 0); + assert(bunyan_key_remove(a, "u64s") == ENOENT); + + bunyan_fini(a); +} + +static void +bad_level(void) +{ + bunyan_logger_t *a; + + assert(bunyan_init("bad level", &a) == 0); + assert(bunyan_stream_add(a, "bar", BUNYAN_L_TRACE - 1, + bunyan_stream_fd, (void *)1) == EINVAL); + assert(bunyan_stream_add(a, "bar", BUNYAN_L_TRACE + 1, + bunyan_stream_fd, (void *)1) == EINVAL); + assert(bunyan_stream_add(a, "bar", BUNYAN_L_DEBUG - 1, + bunyan_stream_fd, (void *)1) == EINVAL); + assert(bunyan_stream_add(a, "bar", BUNYAN_L_INFO + 1, + bunyan_stream_fd, (void *)1) == EINVAL); + assert(bunyan_stream_add(a, "bar", BUNYAN_L_WARN - 1, + bunyan_stream_fd, (void *)1) == EINVAL); + assert(bunyan_stream_add(a, "bar", BUNYAN_L_ERROR + 1, + bunyan_stream_fd, (void *)1) == EINVAL); + assert(bunyan_stream_add(a, "bar", BUNYAN_L_FATAL - 1, + bunyan_stream_fd, (void *)1) == EINVAL); + assert(bunyan_stream_add(a, "bar", -5, + bunyan_stream_fd, (void *)1) == EINVAL); + + bunyan_fini(a); +} + +static void +basic_log(void) +{ + bunyan_logger_t *a; + + assert(bunyan_init("basic", &a) == 0); + assert(bunyan_stream_add(a, "foo", BUNYAN_L_TRACE, + bunyan_stream_fd, (void *)1) == 0); + assert(bunyan_trace(a, "trace", BUNYAN_T_END) == 0); + assert(bunyan_debug(a, "debug", BUNYAN_T_END) == 0); + assert(bunyan_info(a, "info", BUNYAN_T_END) == 0); + assert(bunyan_warn(a, "warn", BUNYAN_T_END) == 0); + assert(bunyan_error(a, "error", BUNYAN_T_END) == 0); + assert(bunyan_fatal(a, "fatal", BUNYAN_T_END) == 0); + + bunyan_fini(a); +} + +static void +crazy_log(void) +{ + bunyan_logger_t *a; + struct in_addr v4; + struct in6_addr v6; + + bzero(&v4, sizeof (struct in_addr)); + bzero(&v6, sizeof (struct in6_addr)); + + assert(bunyan_init("basic", &a) == 0); + assert(bunyan_stream_add(a, "foo", BUNYAN_L_TRACE, + bunyan_stream_fd, (void *)1) == 0); + assert(bunyan_trace(a, "trace", BUNYAN_T_STRING, "s", "foo", + BUNYAN_T_POINTER, "p", (void *)a, BUNYAN_T_IP, "v4", &v4, + BUNYAN_T_IP6, "v6", &v6, BUNYAN_T_BOOLEAN, "b", B_TRUE, + BUNYAN_T_INT32, "i32", 69, BUNYAN_T_INT64, "i64", (uint64_t)6969, + BUNYAN_T_UINT32, "u32", 23, BUNYAN_T_UINT64, "u64", (uint64_t)2323, + BUNYAN_T_DOUBLE, "d", 3.14, + BUNYAN_T_INT64STR, "i64s", (uint64_t)12345, + BUNYAN_T_UINT64STR, "u64s", (uint64_t)54321, BUNYAN_T_END) == 0); + assert(bunyan_debug(a, "debug", BUNYAN_T_STRING, "s", "foo", + BUNYAN_T_POINTER, "p", (void *)a, BUNYAN_T_IP, "v4", &v4, + BUNYAN_T_IP6, "v6", &v6, BUNYAN_T_BOOLEAN, "b", B_TRUE, + BUNYAN_T_INT32, "i32", 69, BUNYAN_T_INT64, "i64", (uint64_t)6969, + BUNYAN_T_UINT32, "u32", 23, BUNYAN_T_UINT64, "u64", (uint64_t)2323, + BUNYAN_T_DOUBLE, "d", 3.14, + BUNYAN_T_INT64STR, "i64s", (uint64_t)12345, + BUNYAN_T_UINT64STR, "u64s", (uint64_t)54321, BUNYAN_T_END) == 0); + assert(bunyan_info(a, "info", BUNYAN_T_STRING, "s", "foo", + BUNYAN_T_POINTER, "p", (void *)a, BUNYAN_T_IP, "v4", &v4, + BUNYAN_T_IP6, "v6", &v6, BUNYAN_T_BOOLEAN, "b", B_TRUE, + BUNYAN_T_INT32, "i32", 69, BUNYAN_T_INT64, "i64", (uint64_t)6969, + BUNYAN_T_UINT32, "u32", 23, BUNYAN_T_UINT64, "u64", (uint64_t)2323, + BUNYAN_T_DOUBLE, "d", 3.14, + BUNYAN_T_INT64STR, "i64s", (uint64_t)12345, + BUNYAN_T_UINT64STR, "u64s", (uint64_t)54321, BUNYAN_T_END) == 0); + assert(bunyan_warn(a, "warn", BUNYAN_T_STRING, "s", "foo", + BUNYAN_T_POINTER, "p", (void *)a, BUNYAN_T_IP, "v4", &v4, + BUNYAN_T_IP6, "v6", &v6, BUNYAN_T_BOOLEAN, "b", B_TRUE, + BUNYAN_T_INT32, "i32", 69, BUNYAN_T_INT64, "i64", (uint64_t)6969, + BUNYAN_T_UINT32, "u32", 23, BUNYAN_T_UINT64, "u64", (uint64_t)2323, + BUNYAN_T_DOUBLE, "d", 3.14, + BUNYAN_T_INT64STR, "i64s", (uint64_t)12345, + BUNYAN_T_UINT64STR, "u64s", (uint64_t)54321, BUNYAN_T_END) == 0); + assert(bunyan_error(a, "error", BUNYAN_T_STRING, "s", "foo", + BUNYAN_T_POINTER, "p", (void *)a, BUNYAN_T_IP, "v4", &v4, + BUNYAN_T_IP6, "v6", &v6, BUNYAN_T_BOOLEAN, "b", B_TRUE, + BUNYAN_T_INT32, "i32", 69, BUNYAN_T_INT64, "i64", (uint64_t)6969, + BUNYAN_T_UINT32, "u32", 23, BUNYAN_T_UINT64, "u64", (uint64_t)2323, + BUNYAN_T_DOUBLE, "d", 3.14, + BUNYAN_T_INT64STR, "i64s", (uint64_t)12345, + BUNYAN_T_UINT64STR, "u64s", (uint64_t)54321, BUNYAN_T_END) == 0); + assert(bunyan_fatal(a, "fatal", BUNYAN_T_STRING, "s", "foo", + BUNYAN_T_POINTER, "p", (void *)a, BUNYAN_T_IP, "v4", &v4, + BUNYAN_T_IP6, "v6", &v6, BUNYAN_T_BOOLEAN, "b", B_TRUE, + BUNYAN_T_INT32, "i32", 69, BUNYAN_T_INT64, "i64", (uint64_t)6969, + BUNYAN_T_UINT32, "u32", 23, BUNYAN_T_UINT64, "u64", (uint64_t)2323, + BUNYAN_T_DOUBLE, "d", 3.14, + BUNYAN_T_INT64STR, "i64s", (uint64_t)12345, + BUNYAN_T_UINT64STR, "u64s", (uint64_t)54321, BUNYAN_T_END) == 0); + + bunyan_fini(a); +} + +static void +child_log(void) +{ + bunyan_logger_t *a, *child; + struct in_addr v4; + struct in6_addr v6; + + bzero(&v4, sizeof (struct in_addr)); + bzero(&v6, sizeof (struct in6_addr)); + + assert(bunyan_init("child", &a) == 0); + assert(bunyan_stream_add(a, "foo", BUNYAN_L_TRACE, + bunyan_stream_fd, (void *)1) == 0); + assert(bunyan_child(a, &child, BUNYAN_T_STRING, "s", "foo", + BUNYAN_T_POINTER, "p", (void *)a, BUNYAN_T_IP, "v4", &v4, + BUNYAN_T_IP6, "v6", &v6, BUNYAN_T_BOOLEAN, "b", B_TRUE, + BUNYAN_T_INT32, "i32", 69, BUNYAN_T_INT64, "i64", (uint64_t)6969, + BUNYAN_T_UINT32, "u32", 23, BUNYAN_T_UINT64, "u64", (uint64_t)2323, + BUNYAN_T_DOUBLE, "d", 3.14, + BUNYAN_T_INT64STR, "i64s", (uint64_t)12345, + BUNYAN_T_UINT64STR, "u64s", (uint64_t)54321, BUNYAN_T_END) == 0); + + bunyan_fini(a); + assert(bunyan_trace(child, "trace", BUNYAN_T_END) == 0); + assert(bunyan_debug(child, "debug", BUNYAN_T_END) == 0); + assert(bunyan_info(child, "info", BUNYAN_T_END) == 0); + assert(bunyan_warn(child, "warn", BUNYAN_T_END) == 0); + assert(bunyan_error(child, "error", BUNYAN_T_END) == 0); + assert(bunyan_fatal(child, "fatal", BUNYAN_T_END) == 0); + + bunyan_fini(child); +} + +static void +crazy_child(void) +{ + bunyan_logger_t *a, *child; + struct in_addr v4; + struct in6_addr v6; + + bzero(&v4, sizeof (struct in_addr)); + bzero(&v6, sizeof (struct in6_addr)); + + assert(bunyan_init("crazy child", &a) == 0); + assert(bunyan_stream_add(a, "foo", BUNYAN_L_TRACE, + bunyan_stream_fd, (void *)1) == 0); + assert(bunyan_key_add(a, BUNYAN_T_STRING, "s", "foo", + BUNYAN_T_POINTER, "p", (void *)a, BUNYAN_T_IP, "v4", &v4, + BUNYAN_T_IP6, "v6", &v6, BUNYAN_T_BOOLEAN, "b", B_TRUE, + BUNYAN_T_INT32, "i32", 69, BUNYAN_T_INT64, "i64", (uint64_t)6969, + BUNYAN_T_UINT32, "u32", 23, BUNYAN_T_UINT64, "u64", (uint64_t)2323, + BUNYAN_T_DOUBLE, "d", 3.14, + BUNYAN_T_INT64STR, "i64s", (uint64_t)12345, + BUNYAN_T_UINT64STR, "u64s", (uint64_t)54321, BUNYAN_T_END) == 0); + assert(bunyan_child(a, &child, BUNYAN_T_END) == 0); + bunyan_fini(a); + + assert(bunyan_stream_remove(child, "foo") == 0); + assert(bunyan_stream_add(child, "bar", BUNYAN_L_TRACE, + bunyan_stream_fd, (void *)1) == 0); + assert(bunyan_key_remove(child, "u64s") == 0); + assert(bunyan_trace(child, "trace", BUNYAN_T_END) == 0); + assert(bunyan_debug(child, "debug", BUNYAN_T_END) == 0); + assert(bunyan_info(child, "info", BUNYAN_T_END) == 0); + assert(bunyan_warn(child, "warn", BUNYAN_T_END) == 0); + assert(bunyan_error(child, "error", BUNYAN_T_END) == 0); + assert(bunyan_fatal(child, "fatal", BUNYAN_T_END) == 0); + + bunyan_fini(child); +} + +int +main(void) +{ + create_handles(); + create_stream(); + create_key(); + bad_level(); + basic_log(); + crazy_log(); + child_log(); + crazy_child(); + + return (0); +} diff --git a/usr/src/test/util-tests/tests/bunyan/bunyan.ksh b/usr/src/test/util-tests/tests/bunyan/bunyan.ksh new file mode 100644 index 0000000000..4ec0f4bd62 --- /dev/null +++ b/usr/src/test/util-tests/tests/bunyan/bunyan.ksh @@ -0,0 +1,26 @@ +#! /usr/bin/ksh +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2014, Joyent, Inc. +# + +# +# Simple wrapper for the classic test.out +# + +set -o errexit + +btest_root=$(dirname $0)/../.. +btest_bin=$btest_root/bin/btest + +LD_PRELOAD=libumem.so UMEM_DEBUG=default $btest_bin >/dev/null diff --git a/usr/src/test/util-tests/tests/dladm/Makefile b/usr/src/test/util-tests/tests/dladm/Makefile index df3997656c..a71332b016 100644 --- a/usr/src/test/util-tests/tests/dladm/Makefile +++ b/usr/src/test/util-tests/tests/dladm/Makefile @@ -17,7 +17,7 @@ include $(SRC)/cmd/Makefile.cmd include $(SRC)/test/Makefile.com ROOTOPTPKG = $(ROOT)/opt/util-tests/tests -PROG = allowed-ips +PROG = allowed-ips vnic-mtu ROOTPROG = $(PROG:%=$(ROOTOPTPKG)/%) diff --git a/usr/src/test/util-tests/tests/dladm/vnic-mtu.ksh b/usr/src/test/util-tests/tests/dladm/vnic-mtu.ksh new file mode 100644 index 0000000000..49daa74f3b --- /dev/null +++ b/usr/src/test/util-tests/tests/dladm/vnic-mtu.ksh @@ -0,0 +1,116 @@ +#!/bin/ksh +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2015 Joyent, Inc. +# + +# +# The purpose of this is to test the MTU property on VNICs, using both +# temporary and persistent properties. To do this, we create an +# Etherstub and then create various VNICs on top of it. +# + +vm_arg0="$(basename $0)" +vm_stub="teststub$$" +vm_vnic="testvnic$$" + +VM_MTU_MIN=576 +VM_MTU_MAX=9000 + +fatal() +{ + typeset msg="$*" + [[ -z "$msg" ]] && msg="failed" + echo "TEST_FAIL: $vm_arg0: $msg" >&2 + + # Try to clean up just in case + dladm delete-vnic $vm_vnic 2>/dev/null + dladm delete-etherstub $vm_stub 2>/dev/null + exit 1 +} + +# +# Validate that the MTU of the datalink dev has the MTU that we expect +# +validate_mtu() +{ + typeset dev=$1 + typeset mtu=$2 + typeset val + + [[ -z "$dev" ]] && fatal "missing required device" + [[ -z "$mtu" ]] && fatal "missing required mtu" + val=$(dladm show-linkprop -c -p mtu -o value $dev) + [[ $? -eq 0 ]] || fatal "failed to get MTU for $dev" + (( $val == $mtu )) || fatal \ + "mtu mismatch on $dev: expected $mtu, got $val" +} + +delete_stub() +{ + dladm delete-etherstub $vm_stub || fatal \ + "failed to delete stub $vm_stub" +} + +create_stub() +{ + dladm create-etherstub $vm_stub || fatal \ + "failed to create stub" + validate_mtu $vm_stub $VM_MTU_MAX +} + +delete_vnic() +{ + dladm delete-vnic $vm_vnic || fatal "failed to delete vnic $vm_vnic" +} + +test_vnic_pass() +{ + typeset mtu=$1 + typeset flags=$2 + + [[ -z "$mtu" ]] && fatal "missing required mtu" + dladm create-vnic $flags -l $vm_stub -p mtu=$mtu $vm_vnic || fatal \ + "failed tocreate vnic: $vm_vnic" + validate_mtu "$vm_vnic" "$mtu" + delete_vnic +} + +test_vnic_fail() +{ + typeset mtu=$1 + typeset flags=$2 + + [[ -z "$mtu" ]] && fatal "missing required mtu" + dladm create-vnic $flags -l $vm_stub -p mtu=$mtu \ + $vm_vnic 2>/dev/null && fatal \ + "created vnic with mtu $mtu, but failure expected" +} + +test_pass() +{ + typeset flags=$1 + + create_stub + test_vnic_pass 1500 $flags + test_vnic_pass 1400 $flags + test_vnic_pass $VM_MTU_MIN $flags + test_vnic_pass $VM_MTU_MAX $flags + test_vnic_fail $((($VM_MTU_MIN - 1))) $flags + test_vnic_fail $((($VM_MTU_MAX + 1))) $flags + delete_stub +} + +test_pass "-t" +test_pass +echo "TEST PASS: $vm_arg0" diff --git a/usr/src/test/util-tests/tests/libnvpair_json/Makefile b/usr/src/test/util-tests/tests/libnvpair_json/Makefile index d1d3585b02..3b48e0b630 100644 --- a/usr/src/test/util-tests/tests/libnvpair_json/Makefile +++ b/usr/src/test/util-tests/tests/libnvpair_json/Makefile @@ -10,14 +10,14 @@ # # -# Copyright (c) 2014 Joyent, Inc. +# Copyright 2015 Joyent, Inc. # include $(SRC)/Makefile.master ROOTOPTPKG = $(ROOT)/opt/util-tests TESTDIR = $(ROOTOPTPKG)/tests/libnvpair_json -ROOTBINDIR = $(ROOTOPTPKG)/bin +TESTBIN = $(ROOTOPTPKG)/bin PROG = print_json @@ -38,9 +38,11 @@ include $(SRC)/test/Makefile.com OBJS = $(PROG:%=%.o) SRCS = $(OBJS:%.o=%.c) -CMDS = $(PROG:%=$(ROOTBINDIR)/%) $(SCRIPTS:%=$(TESTDIR)/%) +CMDS = $(PROG:%=$(TESTBIN)/%) $(SCRIPTS:%=$(TESTDIR)/%) $(CMDS) := FILEMODE = 0555 +DIRS = $(TESTDIR) $(TESTBIN) + LDLIBS += -lnvpair LINTFLAGS += -erroff=E_FUNC_ARG_UNUSED @@ -61,16 +63,13 @@ clobber: clean clean: -$(RM) $(OBJS) -$(CMDS): $(TESTDIR) $(PROG) +$(CMDS): $(DIRS) -$(ROOTBINDIR): - $(INS.dir) - -$(ROOTBINDIR)/%: % - $(INS.file) - -$(TESTDIR): +$(DIRS): $(INS.dir) $(TESTDIR)/%: %.ksh $(INS.rename) + +$(TESTBIN)/%: % + $(INS.file) diff --git a/usr/src/test/util-tests/tests/libnvpair_json/json_08_large_data.ksh b/usr/src/test/util-tests/tests/libnvpair_json/json_08_large_data.ksh new file mode 100644 index 0000000000..ca19e10d06 --- /dev/null +++ b/usr/src/test/util-tests/tests/libnvpair_json/json_08_large_data.ksh @@ -0,0 +1,37 @@ +#!/bin/ksh +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2015, Joyent, Inc. +# + +DIR=$(dirname $(whence $0)) +. ${DIR}/json_common + +BASELINE="$(cat <<EOF +{\ +"o":[\ +$(for i in {1..50}; do + printf '"%s",' 'some_very_big_string_that_takes_up_space' +done)\ +"end"\ +]\ +} +EOF)" + +OUTPUT="$(${DIR}/../../bin/print_json <<-EOF +add_string_array "o" $(for i in {1..50}; do + printf '"%s" ' 'some_very_big_string_that_takes_up_space' +done)"end"; +EOF)" + +complete diff --git a/usr/src/test/util-tests/tests/mergeq/Makefile b/usr/src/test/util-tests/tests/mergeq/Makefile new file mode 100644 index 0000000000..ef6c6abb99 --- /dev/null +++ b/usr/src/test/util-tests/tests/mergeq/Makefile @@ -0,0 +1,64 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2015 Joyent, Inc. +# + +include $(SRC)/Makefile.master + +ROOTOPTPKG = $(ROOT)/opt/util-tests +TESTDIR = $(ROOTOPTPKG)/tests/mergeq + +PROG = mqt +OBJS = mqt.o mergeq.o + +include $(SRC)/cmd/Makefile.cmd +include $(SRC)/cmd/Makefile.ctf +include $(SRC)/test/Makefile.com + +CMDS = $(PROG:%=$(TESTDIR)/%) +$(CMDS) := FILEMODE = 0555 + +CPPFLAGS += -I$(SRC)/lib/mergeq -D_REENTRANT +LDLIBS += -lumem + +all: $(PROG) + +install: all $(CMDS) + +lint: lint_SRCS + +clobber: clean + -$(RM) $(PROG) + +clean: + -$(RM) $(OBJS) + +%.o: %.c + $(COMPILE.c) -o $@ -c $< + $(POST_PROCESS_O) + +%.o: $(SRC)/lib/mergeq/%.c + $(COMPILE.c) -o $@ -c $< + $(POST_PROCESS_O) + +$(PROG): $(OBJS) + $(LINK.c) $(OBJS) -o $@ $(LDLIBS) + $(POST_PROCESS) + +$(CMDS): $(TESTDIR) $(PROG) + +$(TESTDIR): + $(INS.dir) + +$(TESTDIR)/%: % + $(INS.file) diff --git a/usr/src/test/util-tests/tests/mergeq/mqt.c b/usr/src/test/util-tests/tests/mergeq/mqt.c new file mode 100644 index 0000000000..e61e9173d2 --- /dev/null +++ b/usr/src/test/util-tests/tests/mergeq/mqt.c @@ -0,0 +1,217 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2015 Joyent, Inc. + */ + +/* + * mergeq testing routines + */ + +#include <mergeq.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> + +const char * +_umem_debug_init() +{ + return ("default,verbose"); +} + +const char * +_umem_logging_init(void) +{ + return ("fail,contents"); +} + +void * +mergeq_alloc(size_t size) +{ + return (malloc(size)); +} + +/*ARGSUSED*/ +void +mergeq_free(void *buf, size_t size) +{ + free(buf); +} + +static int +mqt_int(void *first, void *second, void **outp, void *arg) +{ + uintptr_t a, b, c; + a = (uintptr_t)first; + b = (uintptr_t)second; + c = a + b; + *outp = (void *)c; + + return (0); +} + +static int +mqt_append(void *first, void *second, void **outp, void *arg) +{ + char *out; + + /* Yes, this leaks, don't worry about it for the test */ + if (asprintf(&out, "%s%s", first, second) != -1) { + *outp = out; + return (0); + } + return (-1); +} + +static int +mqt_fatal(void *first, void *second, void **outp, void *arg) +{ + return (-1); +} + +/* + * Test structures and cases. We really want mq_args to be a flexible array + * member, but then we cant initialize it. Thus we set a fixed size number of + * entries. + */ +typedef struct mq_test { + const char *mq_desc; /* test description/name */ + mergeq_proc_f *mq_proc; /* processing function */ + int mq_rval; /* mergeq_merge return value */ + int mq_uerr; /* user error, if any */ + boolean_t mq_strcmp; /* use strcmp rather than == */ + void *mq_result; /* expected result */ + void **mq_args; /* argument array */ +} mq_test_t; + +static void *mqt_empty_args[] = { NULL }; +static void *mqt_single_args[] = { (void *)42, NULL }; +static void *mqt_double_args[] = { (void *)42, (void *)27, NULL }; +static void *mqt_wrap_args[] = { + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, NULL +}; +static void *mqt_grow_args[] = { + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, NULL +}; +static void *mqt_order_args[] = { "l", "e", "g", "e", "n", "d", " ", "o", "f", + " ", "z", "e", "l", "d", "a", NULL }; + + +static mq_test_t mq_tests[] = { + { "empty", mqt_int, 0, 0, B_FALSE, NULL, mqt_empty_args }, + { "single", mqt_int, 0, 0, B_FALSE, (void *)42, mqt_single_args }, + { "double", mqt_int, 0, 0, B_FALSE, (void *)69, mqt_double_args }, + { "wrap", mqt_int, 0, 0, B_FALSE, (void *)64, mqt_wrap_args }, + { "grow", mqt_int, 0, 0, B_FALSE, (void *)92, mqt_grow_args }, + { "fatal", mqt_fatal, MERGEQ_UERROR, -1, B_FALSE, NULL, + mqt_double_args }, + { "order", mqt_append, 0, 0, B_TRUE, "alegend of zeld", mqt_order_args } +}; + +#define NMQ_TESTS (sizeof (mq_tests) / sizeof (mq_test_t)) + +static void +mq_test_run(mergeq_t *mqp, mq_test_t *mqt) +{ + int ret, err; + void **itemp = mqt->mq_args; + void *out; + + while (*itemp != NULL) { + if ((ret = mergeq_add(mqp, *itemp)) != 0) { + (void) fprintf(stderr, + "test %s: failed to add item: %s\n", + mqt->mq_desc, strerror(errno)); + exit(1); + } + itemp++; + } + + ret = mergeq_merge(mqp, mqt->mq_proc, NULL, &out, &err); + if (ret != mqt->mq_rval) { + (void) fprintf(stderr, "test %s: got incorrect rval. " + "Expected %d, got %d\n", mqt->mq_desc, mqt->mq_rval, ret); + exit(1); + } + + if (ret == MERGEQ_UERROR && err != mqt->mq_uerr) { + (void) fprintf(stderr, "test %s: got incorrect user error. " + "Expected %d, got %d\n", mqt->mq_desc, mqt->mq_uerr, err); + exit(1); + } + + if (ret == 0) { + if (mqt->mq_strcmp == B_TRUE && + strcmp(out, mqt->mq_result) != 0) { + (void) fprintf(stderr, "test %s: got unexpected " + "result: %s, expected %s\n", mqt->mq_desc, out, + mqt->mq_result); + exit(1); + } else if (mqt->mq_strcmp == B_FALSE && out != mqt->mq_result) { + (void) fprintf(stderr, "test %s: got unexpected " + "result: %p, expected %p\n", mqt->mq_desc, out, + mqt->mq_result); + exit(1); + } + } +} + +int +main(void) +{ + int ret, i, t; + mergeq_t *mqp; + int nthreads[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, -1 }; + + for (t = 0; nthreads[t] != -1; t++) { + printf("Beginning tests with %d threads\n", nthreads[t]); + if ((ret = mergeq_init(&mqp, nthreads[t])) != 0) { + fprintf(stderr, "failed to init mergeq: %s\n", + strerror(errno)); + return (1); + } + + for (i = 0; i < NMQ_TESTS; i++) { + mq_test_run(mqp, &mq_tests[i]); + } + + mergeq_fini(mqp); + } + + return (0); +} diff --git a/usr/src/test/util-tests/tests/workq/Makefile b/usr/src/test/util-tests/tests/workq/Makefile new file mode 100644 index 0000000000..ab5455fd86 --- /dev/null +++ b/usr/src/test/util-tests/tests/workq/Makefile @@ -0,0 +1,64 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2015 Joyent, Inc. +# + +include $(SRC)/Makefile.master + +ROOTOPTPKG = $(ROOT)/opt/util-tests +TESTDIR = $(ROOTOPTPKG)/tests/mergeq + +PROG = wqt +OBJS = wqt.o workq.o + +include $(SRC)/cmd/Makefile.cmd +include $(SRC)/cmd/Makefile.ctf +include $(SRC)/test/Makefile.com + +CMDS = $(PROG:%=$(TESTDIR)/%) +$(CMDS) := FILEMODE = 0555 + +CPPFLAGS += -I$(SRC)/lib/mergeq -D_REENTRANT +LDLIBS += -lumem + +all: $(PROG) + +install: all $(CMDS) + +lint: lint_SRCS + +clobber: clean + -$(RM) $(PROG) + +clean: + -$(RM) $(OBJS) + +%.o: %.c + $(COMPILE.c) -o $@ -c $< + $(POST_PROCESS_O) + +%.o: $(SRC)/lib/mergeq/%.c + $(COMPILE.c) -o $@ -c $< + $(POST_PROCESS_O) + +$(PROG): $(OBJS) + $(LINK.c) $(OBJS) -o $@ $(LDLIBS) + $(POST_PROCESS) + +$(CMDS): $(TESTDIR) $(PROG) + +$(TESTDIR): + $(INS.dir) + +$(TESTDIR)/%: % + $(INS.file) diff --git a/usr/src/test/util-tests/tests/workq/wqt.c b/usr/src/test/util-tests/tests/workq/wqt.c new file mode 100644 index 0000000000..bda0b4a9e5 --- /dev/null +++ b/usr/src/test/util-tests/tests/workq/wqt.c @@ -0,0 +1,196 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2015 Joyent, Inc. + */ + +/* + * workq testing routines + * + * What we want to guarantee is that every function is executed exactly once. To + * that end we have the callback function basically increment a global in the + * test around a mutex. + */ + +#include <workq.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <thread.h> +#include <synch.h> + +mutex_t wqt_lock = ERRORCHECKMUTEX; +uintptr_t wqt_count; + +const char * +_umem_debug_init() +{ + return ("default,verbose"); +} + +const char * +_umem_logging_init(void) +{ + return ("fail,contents"); +} + +void * +workq_alloc(size_t size) +{ + return (malloc(size)); +} + +/*ARGSUSED*/ +void +workq_free(void *buf, size_t size) +{ + free(buf); +} + +/*ARGSUSED*/ +int +wqt_fatal(void *item, void *arg) +{ + return (-1); +} + +int +wqt_add(void *item, void *arg) +{ + uintptr_t a = (uintptr_t)item; + + mutex_enter(&wqt_lock); + wqt_count += a; + mutex_exit(&wqt_lock); + + return (0); +} + +typedef struct wq_test { + const char *wq_desc; /* test description/name */ + workq_proc_f *wq_proc; /* processing function */ + int wq_rval; /* workq_work return value */ + int wq_uerr; /* user error, if any */ + uintptr_t wq_sum; /* expected sum */ + void **wq_args; /* argument array */ +} wq_test_t; + +static void *wqt_empty_args[] = { NULL }; +static void *wqt_single_args[] = { (void *)42, NULL }; +static void *wqt_double_args[] = { (void *)42, (void *)27, NULL }; +static void *wqt_wrap_args[] = { + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, NULL +}; +static void *wqt_grow_args[] = { + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, (void *)1, + (void *)1, (void *)1, NULL +}; + +static wq_test_t wq_tests[] = { + { "empty", wqt_add, 0, 0, NULL, wqt_empty_args }, + { "single", wqt_add, 0, 0, 42, wqt_single_args }, + { "double", wqt_add, 0, 0, 69, wqt_double_args }, + { "wrap", wqt_add, 0, 0, 64, wqt_wrap_args }, + { "grow", wqt_add, 0, 0, 92, wqt_grow_args }, + { "fatal", wqt_fatal, WORKQ_UERROR, -1, -1, wqt_double_args } +}; + +#define NWQ_TESTS (sizeof (wq_tests) / sizeof (wq_test_t)) + +static void +wq_test_run(workq_t *wqp, wq_test_t *wqt) +{ + int ret, err; + void **itemp = wqt->wq_args; + + while (*itemp != NULL) { + if ((ret = workq_add(wqp, *itemp)) != 0) { + (void) fprintf(stderr, "test %s: failed to add item: " + "%s\n", wqt->wq_desc, strerror(errno)); + exit(1); + } + itemp++; + } + + wqt_count = 0; + ret = workq_work(wqp, wqt->wq_proc, NULL, &err); + if (ret != wqt->wq_rval) { + (void) fprintf(stderr, "test %s: got incorrect rval. " + "Expected %d, got %d (%d)\n", wqt->wq_desc, wqt->wq_rval, + ret, errno); + exit(1); + } + + if (ret == WORKQ_UERROR && err != wqt->wq_uerr) { + (void) fprintf(stderr, "test %s: got incorrect user error. " + "Expected %d, got %d\n", wqt->wq_desc, wqt->wq_uerr, err); + exit(1); + } + + if (ret == 0 && wqt_count != wqt->wq_sum) { + (void) fprintf(stderr, "test %s: got unexpected " + "result: %d, expected %d\n", wqt->wq_desc, wqt_count, + wqt->wq_sum); + exit(1); + } +} + +int +main(void) +{ + int ret, i, t; + workq_t *wqp; + int nthreads[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, -1 }; + + for (t = 0; nthreads[t] != -1; t++) { + printf("Beginning tests with %d threads\n", nthreads[t]); + if ((ret = workq_init(&wqp, nthreads[t])) != 0) { + fprintf(stderr, "failed to init workq: %s\n", + strerror(errno)); + return (1); + } + + for (i = 0; i < NWQ_TESTS; i++) { + wq_test_run(wqp, &wq_tests[i]); + } + + workq_fini(wqp); + } + + + return (0); +} |
