diff options
Diffstat (limited to 'usr/src/test')
54 files changed, 2550 insertions, 96 deletions
diff --git a/usr/src/test/Makefile b/usr/src/test/Makefile index c951638a63..412288d483 100644 --- a/usr/src/test/Makefile +++ b/usr/src/test/Makefile @@ -27,6 +27,7 @@ SUBDIRS = \ libmlrpc-tests \ net-tests \ os-tests \ + smartos-test \ smbclient-tests \ smbsrv-tests \ test-runner \ diff --git a/usr/src/test/bhyve-tests/runfiles/default.run b/usr/src/test/bhyve-tests/runfiles/default.run index 93101811a5..b59d10ba67 100644 --- a/usr/src/test/bhyve-tests/runfiles/default.run +++ b/usr/src/test/bhyve-tests/runfiles/default.run @@ -9,7 +9,10 @@ # http://www.illumos.org/license/CDDL. # +# # Copyright 2022 Oxide Computer Company +# Copyright 2022 MNX Cloud, Inc. +# [DEFAULT] pre = @@ -21,6 +24,7 @@ outputdir = /var/tmp/test_results [/opt/bhyve-tests/tests/vmm] user = root +pre = vmm_drv_test_init tests = [ 'auto_destruct', 'cpuid_ioctl', @@ -36,6 +40,7 @@ tests = [ 'pause_resume', 'self_destruct' ] +post = vmm_drv_test_fini [/opt/bhyve-tests/tests/kdev] user = root diff --git a/usr/src/test/bhyve-tests/tests/vmm/Makefile b/usr/src/test/bhyve-tests/tests/vmm/Makefile index e557aa2407..658a6b6b64 100644 --- a/usr/src/test/bhyve-tests/tests/vmm/Makefile +++ b/usr/src/test/bhyve-tests/tests/vmm/Makefile @@ -9,7 +9,10 @@ # http://www.illumos.org/license/CDDL. # +# # Copyright 2022 Oxide Computer Company +# Copyright 2022 MNX Cloud, Inc. +# include $(SRC)/cmd/Makefile.cmd include $(SRC)/cmd/Makefile.cmd.64 @@ -30,6 +33,8 @@ PROG = mem_partial \ datarw_constraints \ pause_resume +SCRIPT = vmm_drv_test_fini vmm_drv_test_init + COMMON_OBJS = common.o CLEAN_OBJS = $(PROG:%=%.o) @@ -37,6 +42,7 @@ ROOTOPTPKG = $(ROOT)/opt/bhyve-tests TESTDIR = $(ROOTOPTPKG)/tests/vmm CMDS = $(PROG:%=$(TESTDIR)/%) +CMDS += $(SCRIPT:%=$(TESTDIR)/%) $(CMDS) := FILEMODE = 0555 CSTD= $(CSTD_GNU99) diff --git a/usr/src/test/bhyve-tests/tests/vmm/vmm_drv_test_fini b/usr/src/test/bhyve-tests/tests/vmm/vmm_drv_test_fini new file mode 100755 index 0000000000..79f9b6bcfb --- /dev/null +++ b/usr/src/test/bhyve-tests/tests/vmm/vmm_drv_test_fini @@ -0,0 +1,23 @@ +#!/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 2022 MNX Cloud, Inc. +# + +if ! rem_drv vmm_drv_test; then + printf "failed to remove vmm_drv_test driver\n" 2>&1 + exit 1 +fi + +exit 0 diff --git a/usr/src/test/bhyve-tests/tests/vmm/vmm_drv_test_init b/usr/src/test/bhyve-tests/tests/vmm/vmm_drv_test_init new file mode 100755 index 0000000000..277538432b --- /dev/null +++ b/usr/src/test/bhyve-tests/tests/vmm/vmm_drv_test_init @@ -0,0 +1,24 @@ +#!/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 2022 MNX Cloud, Inc. +# + +if ! add_drv -m '* 0666 root sys' \ + -p 'read_priv_set=sys_devices write_priv_set=sys_devices' vmm_drv_test; then + printf "failed to add vmm_drv_test driver\n" 2>&1 + exit 1 +fi + +exit 0 diff --git a/usr/src/test/libc-tests/runfiles/default.run b/usr/src/test/libc-tests/runfiles/default.run index 9f6269ec71..d5783fcc72 100644 --- a/usr/src/test/libc-tests/runfiles/default.run +++ b/usr/src/test/libc-tests/runfiles/default.run @@ -106,6 +106,8 @@ timeout = 600 [/opt/libc-tests/tests/catopen] [/opt/libc-tests/tests/endian.32] [/opt/libc-tests/tests/endian.64] +[/opt/libc-tests/tests/env-OS-4089.32] +[/opt/libc-tests/tests/env-OS-4089.64] [/opt/libc-tests/tests/env-7076.32] [/opt/libc-tests/tests/env-7076.64] [/opt/libc-tests/tests/err/err.ksh] diff --git a/usr/src/test/libc-tests/tests/Makefile b/usr/src/test/libc-tests/tests/Makefile index 16c002e0ef..e78af2e316 100644 --- a/usr/src/test/libc-tests/tests/Makefile +++ b/usr/src/test/libc-tests/tests/Makefile @@ -36,6 +36,7 @@ SUBDIRS = \ wctype PROGS = \ + env-OS-4089 \ aligned_alloc \ asprintf-14933 \ c11_threads \ diff --git a/usr/src/test/libc-tests/tests/env-OS-4089.c b/usr/src/test/libc-tests/tests/env-OS-4089.c new file mode 100644 index 0000000000..0f52201c79 --- /dev/null +++ b/usr/src/test/libc-tests/tests/env-OS-4089.c @@ -0,0 +1,73 @@ +/* + * 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 2016 Joyent, Inc. + */ + +/* + * Regression test for OS-4089 where doing a putenv() call without an '=' sign + * may lead to a segmentation fault when doing a getenv() depending on the + * circumstances of the environment's layout. Verify putenv() mimics + * unsetenv(). + */ + +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <sys/debug.h> + +int +main(void) +{ + if (putenv("FOO=bar") != 0) { + fprintf(stderr, "failed to put FOO into the environment: %s\n", + strerror(errno)); + return (1); + } + + if (getenv("FOO") == NULL) { + fprintf(stderr, "failed to retrieve FOO from the " + "environment!\n"); + return (1); + } + + VERIFY0(unsetenv("FOO")); + + if (getenv("FOO") != NULL) { + fprintf(stderr, "Somehow retrieved FOO from the " + "environment after unsetenv()!\n"); + return (1); + } + + if (putenv("FOO=bar") != 0) { + fprintf(stderr, "failed to put FOO into the environment: %s\n", + strerror(errno)); + return (1); + } + + if (getenv("FOO") == NULL) { + fprintf(stderr, "failed to retrieve FOO from the " + "environment!\n"); + return (1); + } + + VERIFY0(putenv("FOO")); + + if (getenv("FOO") != NULL) { + fprintf(stderr, "Somehow retrieved FOO from the " + "environment after putenv()!\n"); + return (1); + } + + return (0); +} 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/libc-tests/tests/random/chacha_tv.c b/usr/src/test/libc-tests/tests/random/chacha_tv.c index 636ee114c8..a02c2905ab 100644 --- a/usr/src/test/libc-tests/tests/random/chacha_tv.c +++ b/usr/src/test/libc-tests/tests/random/chacha_tv.c @@ -10,7 +10,7 @@ */ /* - * Copyright (c) 2015, Joyent, Inc. + * Copyright 2019 Joyent, Inc. */ /* @@ -285,7 +285,7 @@ chacha_test(uint8_t *key, uint8_t keylen, uint8_t *iv, uint8_t *bl0, bzero(res0, sizeof (res0)); bzero(res1, sizeof (res1)); chacha_keysetup(&ctx, key, keylen * 8, 0); - chacha_ivsetup(&ctx, iv); + chacha_ivsetup(&ctx, iv, NULL); chacha_encrypt_bytes(&ctx, res0, res0, sizeof (res0)); chacha_encrypt_bytes(&ctx, res1, res1, sizeof (res1)); ret = bcmp(res0, bl0, sizeof (res0)); diff --git a/usr/src/test/os-tests/runfiles/default.run b/usr/src/test/os-tests/runfiles/default.run index de2b29f2f1..d432e7be17 100644 --- a/usr/src/test/os-tests/runfiles/default.run +++ b/usr/src/test/os-tests/runfiles/default.run @@ -26,7 +26,7 @@ timeout = 60 post = outputdir = /var/tmp/test_results -[/opt/os-tests/tests/poll_test] +[/opt/os-tests/tests/poll] user = root tests = ['poll_test', 'epoll_test'] @@ -64,6 +64,10 @@ tests = ['sigqueue_queue_size'] user = root tests = ['sdevfs_eisdir'] +[/opt/os-tests/tests/tmpfs] +user = root +tests = ['tmpfs_badmount', 'tmpfs_enospc'] + [/opt/os-tests/tests/stress] user = root tests = ['dladm-kstat'] @@ -88,6 +92,9 @@ user = root timeout = 180 tests = ['acquire-compare', 'kmc-update', '15146'] +[/opt/os-tests/tests/OS-6097.32] +[/opt/os-tests/tests/OS-6097.64] + [/opt/os-tests/tests/ddi_ufm] user = root tests = ['ufm-test-setup', 'ufm-test', 'ufm-test-cleanup'] diff --git a/usr/src/test/os-tests/tests/Makefile b/usr/src/test/os-tests/tests/Makefile index a30832e8ee..613dd50f8c 100644 --- a/usr/src/test/os-tests/tests/Makefile +++ b/usr/src/test/os-tests/tests/Makefile @@ -39,6 +39,7 @@ SUBDIRS = \ stress \ syscall \ timer \ + tmpfs \ uccid \ $(SUBDIRS_$(MACH)) @@ -46,6 +47,7 @@ PROGS = \ clock_gettime \ eventfd \ odirectory \ + OS-6097 \ ucontext \ writev @@ -61,6 +63,9 @@ ROOTOPTPROGS = $(PROGS32:%=$(ROOTOPTDIR)/%) \ odirectory.32 := LDLIBS += -lsocket odirectory.64 := LDLIBS64 += -lsocket +OS-6097.32 := LDLIBS += -ldlpi +OS-6097.64 := LDLIBS64 += -ldlpi + clock_gettime.32 := LDLIBS += -lproc clock_gettime.32 := CSTD = $(CSTD_GNU99) clock_gettime.64 := LDLIBS64 += -lproc diff --git a/usr/src/test/os-tests/tests/OS-6097.c b/usr/src/test/os-tests/tests/OS-6097.c new file mode 100644 index 0000000000..160c01e9c7 --- /dev/null +++ b/usr/src/test/os-tests/tests/OS-6097.c @@ -0,0 +1,74 @@ +/* + * 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) 2017, Joyent, Inc. + */ + +/* + * Regression test for OS-6097. + */ + +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <libdlpi.h> +#include <sys/debug.h> + +int +main(void) +{ + int ret; + char path[4096]; + uint_t num = 4294967294U; + dlpi_handle_t dh; + + /* + * First, we need to determine a path that doesn't exist to trigger this + * bug. We start with the highest possible number and just decrement + * until we find something. + */ + + while (num > 0) { + struct stat st; + + (void) snprintf(path, sizeof (path), "/dev/net/net%u", num); + + ret = stat(path, &st); + if (ret == -1 && errno == ENOENT) + break; + if (ret == -1) { + (void) fprintf(stderr, "test failed: unexpected error " + "running stat(2) on %s: %s\n", path, + strerror(errno)); + return (1); + } + num--; + } + + /* + * While technically this is a valid entry that we could try, at this + * point we've exhausted so many NICs, there's likely a bug. + */ + if (num == 0) { + (void) fprintf(stderr, "failed to construct a non-existent " + "NIC with a name starting with 'net'\n"); + return (1); + } + + (void) snprintf(path, sizeof (path), "net%u", num); + ret = dlpi_open(path, &dh, 0); + VERIFY3U(ret, ==, DLPI_ENOLINK); + return (0); +} diff --git a/usr/src/test/os-tests/tests/file-locking/Makefile b/usr/src/test/os-tests/tests/file-locking/Makefile index 2f8c6762ad..cd0562777d 100644 --- a/usr/src/test/os-tests/tests/file-locking/Makefile +++ b/usr/src/test/os-tests/tests/file-locking/Makefile @@ -10,7 +10,7 @@ # # -# Copyright 2016 Joyent, Inc. +# Copyright 2020 Joyent, Inc. # include $(SRC)/cmd/Makefile.cmd @@ -28,22 +28,21 @@ SRCS = $(PROGS:%=%.c) $(UTILS:%.o=%.c) PROGS32 = $(PROGS:%=%.32) PROGS64 = $(PROGS:%=%.64) -LINTS = $(PROGS:%=%.ln) -LINTFLAGS += -erroff=E_NAME_DEF_NOT_USED2 -LINTFLAGS += -erroff=E_NAME_USED_NOT_DEF2 - ROOTOPTDIR = $(ROOT)/opt/os-tests/tests/file-locking ROOTOPTPROGS = $(PROGS32:%=$(ROOTOPTDIR)/%) \ $(PROGS64:%=$(ROOTOPTDIR)/%) +all := TARGET = all +install := TARGET = install +clean := TARGET = clean +clobber := TARGET = clobber + .KEEP_STATE: install: $(ROOTOPTPROGS) all: $(PROGS32) $(PROGS64) -lint: $(LINTS) - clean: -rm $(PROGS32) $(PROGS64) @@ -58,9 +57,6 @@ $(ROOTOPTDIR)/%: % $(ROOTOPTDIR)/%: %.ksh $(INS.rename) -%.ln: %.c - $(LINT.c) $< $(UTILS) $(LDLIBS) - %.64.o: %.c $(COMPILE64.c) $< -o $@ diff --git a/usr/src/test/os-tests/tests/poll/Makefile b/usr/src/test/os-tests/tests/poll/Makefile index ae416f9628..feffc744fb 100644 --- a/usr/src/test/os-tests/tests/poll/Makefile +++ b/usr/src/test/os-tests/tests/poll/Makefile @@ -11,7 +11,7 @@ # # Copyright (c) 2012 by Delphix. All rights reserved. -# Copyright 2016 Joyent, Inc. +# Copyright 2017 Joyent, Inc. # include $(SRC)/cmd/Makefile.cmd @@ -26,7 +26,7 @@ poll_test.ln := LDLIBS += -lsocket CSTD = $(CSTD_GNU99) ROOTOPTPKG = $(ROOT)/opt/os-tests -TESTDIR = $(ROOTOPTPKG)/tests +TESTDIR = $(ROOTOPTPKG)/tests/poll CMDS = $(PROG:%=$(TESTDIR)/%) $(CMDS) := FILEMODE = 0555 diff --git a/usr/src/test/os-tests/tests/secflags/secflags_zonecfg.sh b/usr/src/test/os-tests/tests/secflags/secflags_zonecfg.sh index 3ea807f9ae..699b4fe04a 100644 --- a/usr/src/test/os-tests/tests/secflags/secflags_zonecfg.sh +++ b/usr/src/test/os-tests/tests/secflags/secflags_zonecfg.sh @@ -12,14 +12,20 @@ # # Copyright 2015, Richard Lowe. +# Copyright 2019 Joyent, Inc. # Verify that zones can be configured with security-flags LC_ALL=C # Collation is important +IS_SMARTOS=$(uname -v | grep ^joyent_) +if [[ -z "$IS_SMARTOS" ]]; then + create_flag="-b" +fi + expect_success() { name=$1 - (echo "create -b"; + (echo "create $create_flag"; echo "set zonepath=/$name.$$"; cat /dev/stdin; echo "verify"; @@ -46,7 +52,7 @@ expect_fail() { name=$1 expect=$2 - (echo "create -b"; + (echo "create $create_flag"; echo "set zonepath=/$name.$$"; cat /dev/stdin; echo "verify"; diff --git a/usr/src/test/os-tests/tests/tmpfs/Makefile b/usr/src/test/os-tests/tests/tmpfs/Makefile new file mode 100644 index 0000000000..d6515b38fa --- /dev/null +++ b/usr/src/test/os-tests/tests/tmpfs/Makefile @@ -0,0 +1,52 @@ +# +# 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 2016 Joyent, Inc. +# + +include $(SRC)/Makefile.master + +ROOTOPTPKG = $(ROOT)/opt/os-tests +TESTDIR = $(ROOTOPTPKG)/tests/tmpfs + +PROGS = tmpfs_full +SCRIPTS = tmpfs_badmount \ + tmpfs_enospc + +include $(SRC)/cmd/Makefile.cmd +include $(SRC)/test/Makefile.com + +CMDS = $(PROGS:%=$(TESTDIR)/%) $(SCRIPTS:%=$(TESTDIR)/%) +$(CMDS) := FILEMODE = 0555 + +all: $(PROGS) + +install: all $(CMDS) + +lint: + +clobber: clean + -$(RM) $(PROGS) + +clean: + -$(RM) *.o + +$(CMDS): $(TESTDIR) $(PROGS) + +$(TESTDIR): + $(INS.dir) + +$(TESTDIR)/%: %.ksh + $(INS.rename) + +$(TESTDIR)/%: % + $(INS.file) diff --git a/usr/src/test/os-tests/tests/tmpfs/tmpfs_badmount.ksh b/usr/src/test/os-tests/tests/tmpfs/tmpfs_badmount.ksh new file mode 100644 index 0000000000..7e2c4a6095 --- /dev/null +++ b/usr/src/test/os-tests/tests/tmpfs/tmpfs_badmount.ksh @@ -0,0 +1,114 @@ +#!/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 2016 Joyent, Inc. +# + +# +# Test various options to try and mount a tmpfs. Aside from the first to +# verify that we can mount tmpfs at all, these should all fail. +# + +tb_arg0=$(basename $0) +tb_mountpoint="/var/tmp/$0.$$" +tb_mount=/usr/sbin/mount +tb_umount=/usr/sbin/umount + +function fatal +{ + rmdir $tb_mountpoint + typeset msg="$*" + [[ -z "$msg" ]] && msg="test failed" + echo "$tb_arg0: test failed $msg" >&2 + exit 1 +} + +function check_mount +{ + mkdir -p $tb_mountpoint || fatal \ + "failed to make mountpoint $tb_mountpoint" + $tb_mount -F tmpfs swap $tb_mountpoint || fatal \ + "failed to mount tmpfs, check user perms" + $tb_umount $tb_mountpoint || fatal \ + "failed to unmount test point" +} + +function test_one +{ + typeset opts=$1 + + [[ -z "$opts" ]] && fatal "missing required opts" + $tb_mount -F tmpfs -o $opts swap $tb_mountpoint 2>/dev/null + if [[ $? -eq 0 ]]; then + $tb_umount $tb_mountpoint + fatal "successfully mounted with opts $opts, expected failure" + fi +} + +check_mount + +# +# Test invalid percentages. +# +test_one "size=-5%" +test_one "size=200%" +test_one "size=55.55555%" +test_one "size=100.0%" +test_one "size=bad%" +test_one "size=30g%" +test_one "size=%" +test_one "size=%wat" + +# +# Test invalid sizes. Only kmg are valid prefixes. +# +test_one "size=hello;world" +test_one "size=0xnope" +test_one "size=3.14g" +test_one "size=3;14" +test_one "size=thisisanormalsize" +test_one "size=" +test_one "size=100mtry" + +# +# Now, we need to try and trigger a bunch of overflow. We're going to do +# this assuming we're on a 64-bit kernel (which will always overflow a +# 32-bit kernel). +# +test_one "size=20000000000000000000" +test_one "size=1ggggggggggggggggggg" +test_one "size=1mmmmmmmmmmmmmmmmmmm" +test_one "size=1kkkkkkkkkkkkkkkkkkk" +test_one "size=1kkkkkkkkkkkkkkkkkkk" +test_one "size=18014398509481983k" +test_one "size=17592186044416m" +test_one "size=17179869185g" +test_one "size=17179869184g" + +# +# Let's throw a couple bad modes around while we're here. +# +test_one "mode=17777" +test_one "mode=27777" +test_one "mode=37777" +test_one "mode=47777" +test_one "mode=57777" +test_one "mode=67777" +test_one "mode=77777" +test_one "mode=87777" +test_one "mode=97777" +test_one "mode=asdf" +test_one "mode=deadbeef" +test_one "mode=kefka" + +rmdir $tb_mountpoint diff --git a/usr/src/test/os-tests/tests/tmpfs/tmpfs_enospc.ksh b/usr/src/test/os-tests/tests/tmpfs/tmpfs_enospc.ksh new file mode 100644 index 0000000000..a285f306e2 --- /dev/null +++ b/usr/src/test/os-tests/tests/tmpfs/tmpfs_enospc.ksh @@ -0,0 +1,74 @@ +#!/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 2016 Joyent, Inc. +# + +# +# Verify that if we fill up a tmpfs that we can't then perform +# additional things to it that would result in the creation or use of +# kernel memory. +# + +te_arg0=$(basename $0) +te_root=$(dirname $0) +te_bin=$te_root/tmpfs_full +te_mountpoint="/var/tmp/$0.$$" +te_mount=/usr/sbin/mount +te_umount=/usr/sbin/umount +te_testfile=1m +te_mounted= +te_exit=1 + +function fatal +{ + [[ -n "$te_mounted" ]] && $te_umount $te_mountpoint + rmdir $te_mountpoint + typeset msg="$*" + [[ -z "$msg" ]] && msg="test failed" + echo "$te_arg0: test failed $msg" >&2 + exit 1 +} + +function setup +{ + typeset ofile=$te_mountpoint/$te_testfile + + mkdir -p $te_mountpoint || fatal \ + "failed to make mountpoint $te_mountpoint" + $te_mount -F tmpfs swap $te_mountpoint || fatal \ + "failed to mount tmpfs, check user perms" + te_mounted=1 + dd if=/dev/zero of=$ofile bs=1M count=1 2>/dev/null || fatal \ + "failed to create a 1 MB file" + $te_mount -F tmpfs -o remount,size=512k swap $te_mountpoint || + fatal "failed to remount tmpfs" +} + +function run_test +{ + $te_bin $te_mountpoint $te_testfile || fatal "$te_bin failed" +} + +function cleanup +{ + te_mounted= + $te_umount $te_mountpoint || fatal "failed to unmount $te_mountpoint" + rmdir $te_mountpoint || fatal "failed to remove $te_mountpoint" +} + +setup +run_test +cleanup + +exit 0 diff --git a/usr/src/test/os-tests/tests/tmpfs/tmpfs_full.c b/usr/src/test/os-tests/tests/tmpfs/tmpfs_full.c new file mode 100644 index 0000000000..6c6037710b --- /dev/null +++ b/usr/src/test/os-tests/tests/tmpfs/tmpfs_full.c @@ -0,0 +1,94 @@ +/* + * 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 2016 Joyent, Inc. + */ + +/* + * Given a path to a tmpfs that has already been marked as full, attempt to + * perform certain activities on it, all of which should fail with ENOSPC. + */ + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/statvfs.h> +#include <fcntl.h> +#include <errno.h> +#include <strings.h> +#include <sys/debug.h> +#include <unistd.h> + +int +main(int argc, const char *argv[]) +{ + int fd, ret; + struct statvfs vfs; + + if (argc != 3) { + fprintf(stderr, "test failed: missing path or file\n"); + return (1); + } + + if ((fd = open(argv[1], O_RDONLY)) < 0) { + fprintf(stderr, "test failed: failed to open root %s: %s\n", + argv[1], strerror(errno)); + return (1); + } + + if (fstatvfs(fd, &vfs) != 0) { + fprintf(stderr, "test failed: failed to stat vfs for %s: %s\n", + argv[1], strerror(errno)); + return (1); + } + + if (strncmp("tmpfs", vfs.f_basetype, FSTYPSZ) != 0) { + fprintf(stderr, "test failed: asked to run on non-tmpfs\n"); + return (1); + } + + /* + * Once a few additional bugs in tmpfs are fixed, we should double check + * and make sure that the free space here is actually zero before + * continuing. + */ + + /* + * Go through operations that would create nodes and make sure that they + * all fail. + */ + + ret = openat(fd, "Mnemosyne", O_RDWR | O_CREAT, 0755); + VERIFY3S(ret, ==, -1); + VERIFY3S(errno, ==, ENOSPC); + + ret = mkdirat(fd, "Euterpe", 0775); + VERIFY3S(ret, ==, -1); + VERIFY3S(errno, ==, ENOSPC); + + ret = symlinkat("/dev/null", fd, "Melpomene"); + VERIFY3S(ret, ==, -1); + VERIFY3S(errno, ==, ENOSPC); + + ret = linkat(fd, argv[2], fd, "Urania", 0); + VERIFY3S(ret, ==, -1); + VERIFY3S(errno, ==, ENOSPC); + + /* + * Make sure we can't create open extended attributes. + */ + ret = openat(fd, "Lethe", O_RDWR | O_CREAT | O_XATTR); + VERIFY3S(ret, ==, -1); + VERIFY3S(errno, ==, ENOSPC); + + return (0); +} diff --git a/usr/src/test/smartos-test/Makefile b/usr/src/test/smartos-test/Makefile new file mode 100644 index 0000000000..1277987fac --- /dev/null +++ b/usr/src/test/smartos-test/Makefile @@ -0,0 +1,49 @@ +# +# 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 2019 Joyent, Inc. +# + +include $(SRC)/Makefile.master +include ../Makefile.com + +PROGS= smartos-test +FILES= README + +ROOTOPTPKG = $(ROOT)/opt/smartos-test +ROOTBIN = $(ROOTOPTPKG)/bin + +ROOTPROGS= $(PROGS:%=$(ROOTBIN)/%) +$(ROOTPROGS) := FILEMODE = 0555 + +ROOTFILES= $(FILES:%=$(ROOTOPTPKG)/%) +$(ROOTFILES) := FILEMODE = 0444 + +all clean clobber: + +install: $(ROOTPROGS) $(ROOTFILES) + +$(ROOTPROGS): $(ROOTBIN) + +$(ROOTFILES): $(ROOTOPTPKG) + +$(ROOTBIN): + $(INS.dir) + +$(ROOTOPTPKG): + $(INS.dir) + +$(ROOTOPTPKG)/%: % + $(INS.file) + +$(ROOTBIN)/%: %.sh + $(INS.rename) diff --git a/usr/src/test/smartos-test/README b/usr/src/test/smartos-test/README new file mode 100644 index 0000000000..7e38905729 --- /dev/null +++ b/usr/src/test/smartos-test/README @@ -0,0 +1,103 @@ +# +# 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 2019 Joyent. Inc. +# + +Strictly speaking, this is not a set of tests. Rather, it is a wrapper that +automates the configuration of a SmartOS system to prepare it for test +execution, optionally running those tests. + +The smartos-test script should be extracted from the test archive to ensure +the correct version is being executed. + +For example: + +[root@kura /var/tmp]# tar zvxf tests-test_archive-master-20191001T134222Z.tgz ./opt/smartos-test +Decompressing 'tests-test_archive-master-20191001T134222Z.tgz' with '/usr/bin/gzcat'... +x ./opt/smartos-test, 0 bytes, 0 tape blocks +x ./opt/smartos-test/README, 958 bytes, 2 tape blocks +x ./opt/smartos-test/bin, 0 bytes, 0 tape blocks +x ./opt/smartos-test/bin/smartos-test, 10062 bytes, 20 tape blocks +[root@kura /var/tmp]# ./opt/smartos-test/bin/smartos-test -h +Usage: smartos-test [-h] [-c] [-e] [-r] [-w] <path to tests.tgz> + +At least one of -c, -e, -r is required. + + -h print usage + -c configure the system for testing + -e execute known tests + -f skip the check to ensure platform version == test version + -r snapshot or rollback to zones/opt@system-test-smartos-test + before doing any system configuration or test execution + -w when mounting the lofs /usr, make it writable + + +Specifically, the script will: + +* verify that the user has declared that no production data exists on the + test system +* verify we're running in the global zone +* verify the test archive version matches the version of the platform we're + running +* optionally snapshot or rollback /opt to "zones/opt@system-test-smartos-test" +* setup loopback mounts for any files from the smartos "tests-[stamp].tgz" + file that need to be installed to a normally read-only location, and + extract the portions of test archive that must appear in /usr +* extract the remaining test archive contents to /opt and /kernel +* configure pkgsrc +* install required test packages +* execute tests that should all pass + +Over time, we hope to add to the set of tests that are executed. + +After configuring the system for testing, you may choose to run individual +test suites, for example: + + # /opt/util-tests/bin/utiltest +or + # /opt/os-tests/bin/ostest + + +A note on ZFS testing: + +At present, this wrapper does *not* execute the ZFS tests, since they're +more invasive than the other packaged tests. To run those, after configuring +the system for testing, change to the 'ztest' user and set environment +variables. + +In this example, DISKS is the list of three unused disks that will be used +to run the tests. KEEP is a list of zpools that the tests should *not* +destroy: + + # su ztest + $ export DISKS='c2t1d0 c2t2d0 c2t3d0' + $ export KEEP='zones' + $ /opt/zfs-tests/bin/zfstest + +Beware that data loss will occur for any data residing on DISKS and failure to +specify a KEEP pool may also lead to data loss. + + +A note for SmartOS developers: + +The test archive .tgz file is built by the 'tests-tar' Makefile target in +smartos-live.git. + +The manifest of files included in the archive is generated at build-time by +parsing the IPS package manifests from $SRC/pkg/manifests that are listed in +$SRC/Makefile.testarchive in this repository. + +It is important when adding or removing tests that the IPS manifests are +updated. If new test packages are created, they should be added to +$SRC/Makefile.testarchive. + diff --git a/usr/src/test/smartos-test/smartos-test.sh b/usr/src/test/smartos-test/smartos-test.sh new file mode 100755 index 0000000000..cc2055dc8f --- /dev/null +++ b/usr/src/test/smartos-test/smartos-test.sh @@ -0,0 +1,444 @@ +#! /usr/bin/bash +# +# +# 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 2020 Joyent, Inc. +# Copyright 2022 MNX Cloud, Inc. +# + +# +# This script is designed to run on an (effectively) disposable SmartOS +# install to configure the system, install a series of tests from the +# smartos-gate, and execute them. +# It exits 1 if any configuration, setup or test fails. +# + +export PATH=/usr/bin:/usr/sbin:/opt/tools/sbin:/opt/tools/bin:$PATH + +# The pkgsrc packages we will install. +export SMARTOS_TEST_PKGS=" + python39 + sudo + coreutils + gcc10 + gmake +" + +# +# Set $KEEP as a precaution in case we ever end up running the zfs-test suite +# by accident or design. This ensures it never attempts to destroy the 'zones' +# zpool. Note that the ZFS test suite also wants DISKS set to the disks which +# it can create/destroy pools on, but we're not computing that here. +# +if [[ -z "$KEEP" ]]; then + export KEEP="zones" +fi + +# +# Accumulate test suite exit codes and a list of failed tests +# +RESULT=0 +FAILED_TESTS="" + +function fatal { + echo "ERROR: $@" + exit 1 +} + +function warn { + echo "WARNING: $@" +} + +function log { + echo "$@" +} + +function log_must { + echo "Running $@" + $@ || fatal "Error running command." +} + +function log_test { + echo "" + TEST_NAME=$1 + shift + echo "Starting test for $TEST_NAME with $@" + $@ + TEST_RESULT=$? + if [[ $TEST_RESULT -ne 0 ]]; then + FAILED_TESTS="$FAILED_TESTS $TEST_NAME" + fi + RESULT=$(( $RESULT + $TEST_RESULT )) +} + +function log_testrunner { + echo "" + TEST_NAME=$1 + shift + echo "Starting test-runner for $TEST_NAME with $@" + /opt/test-runner/bin/run -c $@ + TEST_RESULT=$? + if [[ $TEST_RESULT -ne 0 ]]; then + FAILED_TESTS="$FAILED_TESTS $TEST_NAME" + fi + RESULT=$(( $RESULT + $TEST_RESULT )) + # test-runner's default log dirs use a timestamp at per-second granularity. + # Sleep here to ensure a unique timestamp per run if consecutive tests + # bail out early. + sleep 1 +} + +function guard_production_data { + + if [[ ! -f "/lib/sdc/.sdc-test-no-production-data" ]]; then + cat <<EOF +To setup and run these tests you must create the file: + /lib/sdc/.sdc-test-no-production-data +after ensuring you have no production data on this system. +EOF + exit 1 + fi +} + +function zone_check { + if [[ $(zonename) != "global" ]]; then + fatal "these tests must be run from the global zone." + fi +} + +# +# Check that the tests.buildstamp file in the test archive matches +# the current platform stamp. Running tests designed for a platform +# that we're not running is a bad idea. +# +function version_check { + PLATFORM_VERSION=$(uname -v | sed -e 's/^joyent_//g') + mkdir -p /tmp/version_check.$$ + tar xzf $1 -C /tmp/version_check.$$ ./tests.buildstamp + TESTS_VERSION=$(cat /tmp/version_check.$$/tests.buildstamp) + rm -rf /tmp/version_check.$$ + log "Platform version: $PLATFORM_VERSION" + log " Tests version: $TESTS_VERSION" + if [[ "$PLATFORM_VERSION" != "$TESTS_VERSION" ]]; then + fatal "mismatched platform version and tests version!" + fi +} + +function snapshot_rollback_opt { + snapshot="system-test-smartos-test" + has_snapshot=$(zfs list zones/opt@$snapshot 2> /dev/null) + if [[ -n "$has_snapshot" ]]; then + log_must zfs rollback zones/opt@$snapshot + else + log_must zfs snapshot zones/opt@$snapshot + fi +} + +# +# Since some tests want to deliver to /usr which is read-only on SmartOS, +# we make a temporary directory, dump the current /usr there, extract our +# content to it, then lofs-mount it over the real thing. +# +function add_loopback_mounts { + test_archive=$1 + lofs_home=/var/tmp/smartos-test-loopback + + # If /usr is already lofs mounted, and pointing at $lofs_home, just + # extract our new test bits on top. Ideally we'd just unmount it, + # but while running this script, there's a good chance that the dataset + # will be busy and the umount would fail. + FS=$(/bin/df -n /usr | awk '{print $NF'}) + if [[ "$FS" == "lofs" ]]; then + is_test_lofs=$(mount | grep ^/usr | grep "$lofs_home/usr ") + if [[ -z "$is_test_lofs" ]]; then + fatal "unsupported: existing lofs mount for /usr is not $lofs_home" + else + log "Extracting new test archive to lofs-mounted /usr" + # extract the current test archive to it + log_must tar -xzf $test_archive -C $lofs_home ./usr + fi + # Otherwise, setup a lofs mount for it. + else + log "Creating new lofs mount for /usr on $lofs_home" + rm -rf $lofs_home + mkdir -p $lofs_home + find /usr | cpio -pdum $lofs_home + log_must tar -xzf $test_archive -C $lofs_home ./usr + # keep /usr read-only in an attempt to preserve smartos behaviour + # unless specifically asked to + if [[ "$mount_usr_rw" = "true" ]]; then + mount_opts="-o rw" + else + mount_opts="-o ro" + fi + log_must mount -O -F lofs $mount_opts $lofs_home/usr /usr + fi +} + +# +# Extract the non-/usr parts of the test archive +# +function extract_remaining_test_bits { + log_must tar -xzf $1 -C / \ + ./opt ./kernel ./tests.manifest.gen ./tests.buildstamp +} + +function setup_pkgsrc { + + if [[ -f /opt/tools/etc/pkgin/repositories.conf ]]; then + log "Pkgsrc bootstrap already setup, continuing" + return + fi + + # We should always use the same pkgsrc version as we have installed + # on the build machine in case any of our tests link against libraries + # in /opt/tools + PKGSRC_STEM="https://pkgsrc.smartos.org/packages/SmartOS/bootstrap" + BOOTSTRAP_TAR="bootstrap-2021Q4-tools.tar.gz" + BOOTSTRAP_SHA="c427cb1ed664fd161d8e12c5191adcae7aee68b4" + + # Ensure we are in a directory with enough space for the bootstrap + # download, by default the SmartOS /root directory is limited to the size + # of the ramdisk. + cd /var/tmp + + # Download the bootstrap kit to the current directory. Note that we + # currently pass "-k" to skip SSL certificate checks as the GZ doesn't + # install them. + log_must curl -kO ${PKGSRC_STEM}/${BOOTSTRAP_TAR} + + # Verify the SHA1 checksum. + [[ "${BOOTSTRAP_SHA}" = "$(/bin/digest -a sha1 ${BOOTSTRAP_TAR})" ]] || \ + fatal "checksum failure for ${BOOTSTRAP_TAR}, expected ${BOOTSTRAP_SHA}" + + # Install bootstrap kit to /opt/tools + log_must tar -zxpf ${BOOTSTRAP_TAR} -C / +} + +function install_required_pkgs { + + log_must pkgin -y in ${SMARTOS_TEST_PKGS} +} + +function add_test_accounts { + + grep -q '^cyrus:' /etc/passwd + if [[ $? -ne 0 ]]; then + log "Adding cyrus user" + echo "cyrus:x:977:1::/zones/global/cyrus:/bin/sh" >> /etc/passwd + if ! grep -q '^cyrus:' /etc/shadow; then + echo "cyrus:*LK*:::::::" >> /etc/shadow + fi + mkdir -p /zones/global/cyrus + chown cyrus /zones/global/cyrus + fi + grep -q '^ztest:' /etc/passwd + if [[ $? -ne 0 ]]; then + log "Adding ztest user" + echo "ztest:x:978:1::/zones/global/ztest:/bin/sh" >> /etc/passwd + if ! grep -q '^ztest:' /etc/shadow; then + # For sudo to work, the ztest account must not be locked + echo "ztest:NP:::::::" >> /etc/shadow + fi + mkdir -p /zones/global/ztest + chown ztest /zones/global/ztest + zprofile=/zones/global/ztest/.profile + if [[ ! -f $zprofile ]]; then + cat > $zprofile <<-EOF +PATH=/bin:/usr/bin:/sbin:/usr/sbin:/opt/tools/bin:/opt/tools/sbin:/opt/zfs-tests/bin +export PATH + +KEEP="zones" +export KEEP +EOF + + if [[ -n "$DISKS" ]]; then + # NOTE: This will be enough to make this script's execute-tests + # invocation run the ZFS test suite. + echo "DISKS=\"$DISKS\"" >> $zprofile + echo "export DISKS" >> $zprofile + else + msg='echo Please set \$DISKS appropriate before running zfstest' + echo $msg >> $zprofile + fi + + chown ztest $zprofile + fi + fi + if [[ ! -f /opt/tools/etc/sudoers.d/ztest ]]; then + mkdir -p /opt/tools/etc/sudoers.d + echo "ztest ALL=(ALL) NOPASSWD: ALL" >> /opt/tools/etc/sudoers.d/ztest + fi +} + +function zfs_test_check { + # DISKS is set either in our environment, or in the .profile of ~ztest. + zprofile=/zones/global/ztest/.profile + zdisksvar=$(su - ztest -c 'echo $DISKS' | tail -1) + + # Check for KEEP too. + grep -q ^KEEP= $zprofile || \ + fatal "Cannot run ZFS test, you need KEEP set in your ztest's environment" + + # If neither are set DO NOT RUN the ztests. + if [[ -z $DISKS && -z $zdisksvar ]]; then + fatal "Cannot run ZFS test, you need DISKS set in your or ztest's environment" + fi + + # Check if they are both non-zero and different. + if [[ -n "$DISKS" && -n "$zdisksvar" && "$DISKS" != "$zdisksvar" ]]; then + log "DISKS in current root environment: $DISKS" + log "DISKS in user ztest's environment: $zdisksvar" + fatal "Pleast reconcile these two before running the ZFS tests." + fi + + if [[ -z "$zdisksvar" ]]; then + # put DISKS into ztest's .profile. + echo "DISKS=\"$DISKS\"" >> $zprofile + echo "export DISKS" >> $zprofile + fi + + # OKAY, now we can run it! + log_test zfstest su - ztest -c /opt/zfs-tests/bin/zfstest +} + +# +# By using log_test or log_testrunner, we accumulate the exit codes from each +# test run to $RESULT. +# +# We don't - yet - run net-tests, smbclient-tests, zfs-tests, or the dtrace +# suite. +# +function execute_tests { + + log "Starting test runs" + log_test bhyvetest /opt/bhyve-tests/bin/bhyvetest + log_testrunner crypto-tests /opt/crypto-tests/runfiles/default.run + log_testrunner elf-tests /opt/elf-tests/runfiles/default.run + log_testrunner libc-tests /opt/libc-tests/runfiles/default.run + log_test vndtest /opt/vndtest/bin/vndtest -a + log_testrunner util-tests /opt/util-tests/runfiles/default.run + log_testrunner os-tests /opt/os-tests/runfiles/default.run + zfs_test_check + + if [[ -n "$FAILED_TESTS" ]]; then + echo "" + log "Failures were seen in the following test suites: $FAILED_TESTS" + fi + +} + +function usage { + echo "Usage: smartos-test [-h] [-c] [-e] [-r] [-w] <path to tests.tgz>" + echo "" + echo "At least one of -c, -e, -r is required." + echo "" + echo " -h print usage" + echo " -c configure the system for testing" + echo " -e execute known tests" + echo " -f skip the check to ensure platform version == test version" + echo " -r snapshot or rollback to zones/opt@system-test-smartos-test" + echo " before doing any system configuration or test execution" + echo " -w when mounting the lofs /usr, make it writable" +} + +mount_usr_rw=false +skip_version_check=false +do_configure=false +do_execute=false +do_rollback=false + +# +# Main +# +while getopts "cefrwh" opt; do + case "${opt}" in + c) + do_configure=true + ;; + e) + do_execute=true + ;; + f) + skip_version_check=true + ;; + r) + do_rollback=true + ;; + h) + usage + exit 2 + ;; + w) + mount_usr_rw=true + ;; + *) + log "unknown argument ${opt}" + usage + exit 2 + esac +done +shift $((OPTIND - 1)) + +test_archive=$1 + +if [[ -z "$test_archive" ]]; then + log "missing test archive argument." + usage + exit 1 +fi + +if [[ ! -f "$test_archive" ]]; then + usage + fatal "unable to access test archive at $test_archive" +fi + +if [[ "$do_rollback" = false && \ + "$do_configure" = false && \ + "$do_execute" = false ]]; then + log "nothing to do: use at least one of -r -e -c" + usage + exit 2 +fi + +if [[ "$skip_version_check" = false ]]; then + version_check $1 +fi + +guard_production_data +zone_check + +if [[ $do_rollback = true ]]; then + snapshot_rollback_opt +fi + +if [[ $do_configure = true ]]; then + add_loopback_mounts $test_archive + extract_remaining_test_bits $test_archive + add_test_accounts + setup_pkgsrc + install_required_pkgs + # Enable per-process coredumps, some tests assume they're pre-set. + log_must coreadm -e process + log "This system is now configured to run the SmartOS tests." +fi + +if [[ "$do_execute" = true ]]; then + execute_tests +fi + +if [[ $RESULT -gt 0 ]]; then + exit 1 +else + exit 0 +fi diff --git a/usr/src/test/test-runner/cmd/run b/usr/src/test/test-runner/cmd/run index 9e2e53333d..ce1bf1419c 100644 --- a/usr/src/test/test-runner/cmd/run +++ b/usr/src/test/test-runner/cmd/run @@ -1,4 +1,4 @@ -#!@PYTHON@ +#!/usr/bin/env python # # This file and its contents are supplied under the terms of the @@ -16,8 +16,13 @@ # Copyright (c) 2017, Chris Fraire <cfraire@me.com>. # Copyright 2019 Joyent, Inc. # Copyright 2020 OmniOS Community Edition (OmniOSce) Association. +# Copyright 2022 MNX Cloud, Inc. # +# NOTE: For SmartOS, the @PYTHON@ macro defaults to /opt/local, which is +# not the case for the SmartOS global zone's pkgsrc installation (/opt/tools). +# So use /usr/bin/env because the smartos-test script sets PATH appropriately. + from __future__ import print_function import sys PY3 = sys.version_info[0] == 3 @@ -51,6 +56,14 @@ TESTDIR = '/opt/zfs-tests/' KILL = '/usr/bin/kill' TRUE = '/usr/bin/true' SUDO = '/usr/bin/sudo' +SU = '/usr/bin/su' + +# The location of sudo(1) varies by illumos distribution. +if os.path.isfile('/usr/bin/sudo'): + SUDO = '/usr/bin/sudo' +else: + SUDO = '/opt/tools/bin/sudo' + retcode = 0 @@ -196,7 +209,21 @@ User: %s sudo is required, this user was verified previously. """ self.killed = True - do_sudo = len(self.user) != 0 + cur_user = getpwuid(os.getuid()).pw_name + + # + # The test runs in a child process of the process performing + # the kill and this child process may be owned by a different + # user (specified by self.user). If this is the case, and the + # parent process is not running as root, then sudo must be + # used. The verify_user function should prevent us from ever + # getting here on a system which doesn't have sudo. + # + if len(self.user) != 0 and self.user != cur_user and cur_user != 'root': + do_sudo = True + else: + do_sudo = False + signal = '-TERM' cmd = [SUDO, KILL, signal, str(proc.pid)] @@ -212,15 +239,23 @@ User: %s def update_cmd_privs(self, cmd, user): """ If a user has been specified to run this Cmd and we're not already - running as that user, prepend the appropriate sudo command to run - as that user. + running as that user, prepend the appropriate sudo command to + run as that user. If running as root use su instead. The + verify_user function should prevent us from ever getting here + on a system which doesn't have sudo. + """ - me = getpwuid(os.getuid()) - if not user or user == me: + cur_user = getpwuid(os.getuid()).pw_name + + if not user or user == cur_user: return cmd - ret = '%s -E -u %s %s' % (SUDO, user, cmd) + if cur_user == 'root': + ret = '%s %s -c %s' % (SU, user, cmd) + else: + ret = '%s -E -u %s %s' % (SUDO, user, cmd) + return ret.split(' ') def collect_output(self, proc): @@ -865,14 +900,28 @@ def verify_file(pathname): def verify_user(user, logger): """ - Verify that the specified user exists on this system, and can execute - sudo without being prompted for a password. + Verify that the specified user exists on this system, and can + execute sudo without being prompted for a password. If the user + executing the test is the same as the requested user then this + check is skipped. If the user executing the test is root this + check is skipped as su can be used instead. """ + testcmd = [SUDO, '-n', '-u', user, TRUE] if user in Cmd.verified_users: return True + cur_user = getpwuid(os.getuid()).pw_name + + if user == cur_user or cur_user == 'root': + Cmd.verified_users.append(user) + return True + + if not os.path.isfile(SUDO): + logger.info("Warning: this test requires sudo but it doesn't exist.") + return False + try: _ = getpwnam(user) except KeyError: diff --git a/usr/src/test/util-tests/runfiles/default.run b/usr/src/test/util-tests/runfiles/default.run index 4d9acd9d47..362c3a49a9 100644 --- a/usr/src/test/util-tests/runfiles/default.run +++ b/usr/src/test/util-tests/runfiles/default.run @@ -28,11 +28,13 @@ outputdir = /var/tmp/test_results [/opt/util-tests/tests/printf_test] [/opt/util-tests/tests/allowed-ips] [/opt/util-tests/tests/set-linkprop] +[/opt/util-tests/tests/show-overlay-exit] +[/opt/util-tests/tests/vnic-mtu] +[/opt/util-tests/tests/bunyan/bunyan] [/opt/util-tests/tests/libsff/libsff] [/opt/util-tests/tests/libjedec_test] [/opt/util-tests/tests/smbios] -[/opt/util-tests/tests/show-overlay-exit] user = root # @@ -47,6 +49,8 @@ user = root [/opt/util-tests/tests/mergeq/mqt] [/opt/util-tests/tests/mergeq/wqt] +[/opt/util-tests/tests/dis/distest] + [/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 c75f26cf85..f26494e0ce 100644 --- a/usr/src/test/util-tests/tests/Makefile +++ b/usr/src/test/util-tests/tests/Makefile @@ -21,6 +21,7 @@ SUBDIRS = \ ar \ awk \ + bunyan \ chown \ ctf \ date \ 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..f6be13afa2 --- /dev/null +++ b/usr/src/test/util-tests/tests/bunyan/btest.c @@ -0,0 +1,316 @@ +/* + * 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); + + assert(bunyan_key_remove(a, "p") == ENOENT); + + 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); + + assert(bunyan_key_remove(child, "p") == 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/dis/distest.ksh b/usr/src/test/util-tests/tests/dis/distest.ksh index 37a5dd231a..f32f858ef1 100644 --- a/usr/src/test/util-tests/tests/dis/distest.ksh +++ b/usr/src/test/util-tests/tests/dis/distest.ksh @@ -11,7 +11,7 @@ # # -# Copyright 2018 Joyent, Inc. +# Copyright 2020 Joyent, Inc. # # @@ -50,6 +50,7 @@ dt_nodefault= dt_tests= dt_tnum=0 dt_tfail=0 +dt_txfail=0 dt_tsuc=0 dt_origwd= dt_root= @@ -141,10 +142,25 @@ handle_failure() mv $dir $faildir cp $source $faildir/ cp $out $faildir/ - printf "%s " "failed " + + # + # Our pkgsrc gas is too old (2.26.1) to assemble these. + # + xfails=("32.vaes.s" "32.gfni.s" "32.avx512_vpclmulqdq.s" + "64.vaes.s" "64.gfni.s" "64.avx512_vpclmulqdq.s") + testname=$(basename $source) + printf '%s\n' ${xfails[@]} | grep "^$testname$" >/dev/null + + if [[ $? -eq 0 ]]; then + printf "%s " "expected fail " + ((dt_txfail++)) + else + printf "%s " "failed " + ((dt_tfail++)) + fi + [[ -n $reason ]] && printf "%s " $reason printf "%s\n" "$faildir" - ((dt_tfail++)) } # @@ -271,6 +287,7 @@ libdis Results Tests passed: $dt_tsuc Tests failed: $dt_tfail +Tests expected to fail: $dt_txfail Tests ran: $dt_tnum EOF } diff --git a/usr/src/test/util-tests/tests/dladm/Makefile b/usr/src/test/util-tests/tests/dladm/Makefile index 50ef1b876a..8bbc8e3841 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 set-linkprop show-overlay-exit +PROG = allowed-ips set-linkprop show-overlay-exit vnic-mtu ROOTPROG = $(PROG:%=$(ROOTOPTPKG)/%) diff --git a/usr/src/test/util-tests/tests/dladm/allowed-cids.ksh b/usr/src/test/util-tests/tests/dladm/allowed-cids.ksh new file mode 100644 index 0000000000..9b62962baf --- /dev/null +++ b/usr/src/test/util-tests/tests/dladm/allowed-cids.ksh @@ -0,0 +1,95 @@ +#!/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 2017 Joyent, Inc. +# + +source ./common.ksh + +property="allowed-dhcp-cids" + +setup + +# Valid hexadecimal strings +epass 0x1234 +epass 0x123456789abcdef0 +epass 0x123456789abcdef0 + +# Hex strings w/ an odd number of characters are not allowed +efail 0x0 +efail 0x1 +efail 0x1fa +efail 0xfba39e2 + +# Invalid hexadecimal strings +efail 0xz +efail 0x01234567q12 +efail 0x=+ +efail 0x-1 +efail 0x1,2,3 + +# Valid RFC 3315 DUID strings + +## DUID-LLT +epass 1.1.1234.90:b8:d0:81:91:30 +epass 1.1.1512434853.90:b8:d0:81:91:30 +epass 1.1.28530123.90:b8:d0:81:91:30 +epass 1.6.1512434853.14:10:9f:d0:5b:d3 + +## DUID-EN +epass 2.9.0CC084D303000912 +epass 2.9.0cc084d303000912 +epass 2.32473.45ab +epass 2.38678.0123abcd + +## DUID-LL +epass 3.1.90:b8:d0:81:91:30 +epass 3.1.90:b8:d0:4b:c7:3b +epass 3.1.2:8:20:a4:4d:ee +epass 3.6.14:10:9f:d0:5b:d3 + +# Invalid RFC 3315 DUID strings + +## DUID-LLT +efail 1.1.12a34.90:b8:d0:81:91:30 +efail 1.1.15-33.90:b8:d0:81:91:30 +efail 1.1.98+123.90:b8:d0:81:91:30 +efail 3.z.1512434853.14:10:9f:d0:5b:d3 +efail 3.6.1512434853.q4:10:9f:d0:5b:d3 + +## DUID-EN +efail 2.32473.45a +efail 2.9.Z +efail 2.9.-12 +efail 2.QZ4.45a +efail 2.38d78.0123abcd + +## DUID-LL +efail 3.wy.90:b8:d0:81:91:30 +efail 3.1.90:z8:di:ob:c7:3b +efail 3.1.5.2:8:20:a4:4d:ee + +## Uknown DUID forms +efail 4.1.45a +efail 9.1.45a +efail 23.1.45a + +# Random strings of bytes are also accepted, +# if they don't have the above prefixes. +epass 1234 +epass abcdef +epass qsxasdasdfgfdgkj123455 +epass 0x + +cleanup +printf "TEST PASS: $ai_arg0\n" diff --git a/usr/src/test/util-tests/tests/dladm/allowed-ips.ksh b/usr/src/test/util-tests/tests/dladm/allowed-ips.ksh index 866b8c7966..4802f86286 100644 --- a/usr/src/test/util-tests/tests/dladm/allowed-ips.ksh +++ b/usr/src/test/util-tests/tests/dladm/allowed-ips.ksh @@ -11,47 +11,12 @@ # # -# Copyright (c) 2014, Joyent, Inc. +# Copyright 2016 Joyent, Inc. # -ai_arg0="$(basename $0)" -ai_stub="teststub$$" -ai_vnic="testvnic$$" +source ./common.ksh -function fatal -{ - typeset msg="$*" - [[ -z "$msg" ]] && msg="failed" - echo "TEST_FAIL: $vt_arg0: $msg" >&2 - exit 1 -} - -function setup -{ - dladm create-etherstub $ai_stub || fatal "failed to create etherstub" - dladm create-vnic -l $ai_stub $ai_vnic || fatal "failed to create vnic" -} - -function cleanup -{ - dladm delete-vnic $ai_vnic || fatal "failed to remove vnic" - dladm delete-etherstub $ai_stub || fatal "failed to remove etherstub" -} - -function runtest -{ - dladm set-linkprop -p allowed-ips="$@" $ai_vnic 2>/dev/null -} - -function epass -{ - runtest $* || fatal "allowed-ips=$* failed, expected success\n" -} - -function efail -{ - runtest $* && fatal "allowed-ips=$* succeeded, expected failure\n" -} +property="allowed-ips" # # Run through all IPv6 prefixes for validity with a token prefix @@ -204,4 +169,4 @@ epass fe80::/15 epass fe82::/15 cleanup -printf "TEST PASS: $ai_arg0" +printf "TEST PASS: $ai_arg0\n" diff --git a/usr/src/test/util-tests/tests/dladm/common.ksh b/usr/src/test/util-tests/tests/dladm/common.ksh new file mode 100644 index 0000000000..e5301d0a52 --- /dev/null +++ b/usr/src/test/util-tests/tests/dladm/common.ksh @@ -0,0 +1,57 @@ +#!/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 2017 Joyent, Inc. +# + +ai_arg0="$(basename $0)" +ai_stub="teststub$$" +ai_vnic="testvnic$$" + +typeset property + +function fatal +{ + typeset msg="$*" + [[ -z "$msg" ]] && msg="failed" + echo "TEST_FAIL: $ai_arg0: $msg" >&2 + exit 1 +} + +function setup +{ + dladm create-etherstub $ai_stub || fatal "failed to create etherstub" + dladm create-vnic -l $ai_stub $ai_vnic || fatal "failed to create vnic" +} + +function cleanup +{ + dladm delete-vnic $ai_vnic || fatal "failed to remove vnic" + dladm delete-etherstub $ai_stub || fatal "failed to remove etherstub" +} + +function runtest +{ + [[ -z "$property" ]] && fatal "missing property to set" + dladm set-linkprop -p $property="$@" $ai_vnic 2>/dev/null +} + +function epass +{ + runtest $* || fatal "$property=$* failed, expected success\n" +} + +function efail +{ + runtest $* && fatal "$property=$* succeeded, expected failure\n" +} diff --git a/usr/src/test/util-tests/tests/dladm/dynamic-methods.ksh b/usr/src/test/util-tests/tests/dladm/dynamic-methods.ksh new file mode 100644 index 0000000000..4ed64a92b4 --- /dev/null +++ b/usr/src/test/util-tests/tests/dladm/dynamic-methods.ksh @@ -0,0 +1,45 @@ +#!/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 2017 Joyent, Inc. +# + +source ./common.ksh + +property="dynamic-methods" + +setup + +# All valid values on their own +epass slaac +epass dhcpv4 +epass dhcpv6 +epass addrconf + +# Combinations of values +epass slaac,dhcpv4 +epass slaac,dhcpv6 +epass dhcpv4,dhcpv6 +epass dhcpv4,addrconf +epass dhcpv4,dhcpv6,slaac + +# Illegal values +efail dhcpv8 +efail slaac,dhcpv8 +efail slack +efail ipv6 +efail dhcp +efail dhcpv + +cleanup +printf "TEST PASS: $ai_arg0\n" 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..cfb48e2e65 --- /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 to create 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/grep_xpg4/grep_test.ksh b/usr/src/test/util-tests/tests/grep_xpg4/grep_test.ksh index 2456da0ffe..8724cbcb01 100644 --- a/usr/src/test/util-tests/tests/grep_xpg4/grep_test.ksh +++ b/usr/src/test/util-tests/tests/grep_xpg4/grep_test.ksh @@ -18,6 +18,8 @@ # XGREP=${XGREP:=/usr/bin/grep} + +MY_TESTS=${MY_TESTS:=/opt/util-tests} FILEDIR=$MY_TESTS/tests/files/grep OUTFILE=/tmp/grep_test.out.$$ FLAGSFILE=/tmp/grep_flags.$$ diff --git a/usr/src/test/util-tests/tests/libnvpair_json/Makefile b/usr/src/test/util-tests/tests/libnvpair_json/Makefile index faa76094fe..633b515f19 100644 --- a/usr/src/test/util-tests/tests/libnvpair_json/Makefile +++ b/usr/src/test/util-tests/tests/libnvpair_json/Makefile @@ -17,7 +17,7 @@ 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 # intentional abort() @@ -62,16 +64,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/libnvpair_json/print_json.c b/usr/src/test/util-tests/tests/libnvpair_json/print_json.c index e34ae8f7b1..9ac19b1bd1 100644 --- a/usr/src/test/util-tests/tests/libnvpair_json/print_json.c +++ b/usr/src/test/util-tests/tests/libnvpair_json/print_json.c @@ -814,7 +814,7 @@ main(int argc, char **argv) /* * Print the resultant list, and a terminating newline: */ - if (nvlist_print_json(stdout, lw->lw_nvl[0]) != 0 || + if (nvlist_print_json(stdout, lw->lw_nvl[0]) < 0 || fprintf(stdout, "\n") < 0) goto out; diff --git a/usr/src/test/util-tests/tests/mdb/typedef/tst.dellist.mdb.out b/usr/src/test/util-tests/tests/mdb/typedef/tst.dellist.mdb.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/usr/src/test/util-tests/tests/mdb/typedef/tst.dellist.mdb.out diff --git a/usr/src/test/util-tests/tests/mdb/typedef/tst.emptylist.mdb.out b/usr/src/test/util-tests/tests/mdb/typedef/tst.emptylist.mdb.out new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/usr/src/test/util-tests/tests/mdb/typedef/tst.emptylist.mdb.out diff --git a/usr/src/test/zfs-tests/cmd/scripts/zfstest.ksh b/usr/src/test/zfs-tests/cmd/scripts/zfstest.ksh index 3d53ef5fae..527c89163f 100644 --- a/usr/src/test/zfs-tests/cmd/scripts/zfstest.ksh +++ b/usr/src/test/zfs-tests/cmd/scripts/zfstest.ksh @@ -14,8 +14,10 @@ # # Copyright (c) 2012, 2016 by Delphix. All rights reserved. # Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved. +# Copyright 2019 Joyent, Inc. # Copyright 2021 Tintri by DDN, Inc. All rights reserved. # Copyright 2020 OmniOS Community Edition (OmniOSce) Association. +# Copyright 2022 MNX Cloud, Inc. # export PATH="/usr/bin" @@ -72,6 +74,8 @@ function find_runfile distro=openindiana elif [[ 0 -ne $(grep -c OmniOS /etc/release 2>/dev/null) ]]; then distro=omnios + elif [[ 0 -ne $(grep -c SmartOS /etc/release 2>/dev/null) ]]; then + distro=smartos fi [[ -n $distro ]] && echo $COMMON,$STF_SUITE/runfiles/$distro.run @@ -128,6 +132,18 @@ function constrain_path # Special case links ln -s /usr/gnu/bin/dd $PATHDIR/gnu_dd + + # SmartOS does not ship some required commands by default. + # Link to them in the package manager's namespace. + pkgsrc_bin=/opt/tools/bin + pkgsrc_packages="sudo truncate python base64 shuf sha256sum" + for pkg in $pkgsrc_packages; do + if [[ ! -x $PATHDIR/$pkg ]]; then + rm $PATHDIR/$pkg && + ln -s $pkgsrc_bin/$pkg $PATHDIR/$pkg || + fail "Couldn't link $pkg" + fi + done } constrain_path diff --git a/usr/src/test/zfs-tests/cmd/watch_dir/Makefile b/usr/src/test/zfs-tests/cmd/watch_dir/Makefile new file mode 100644 index 0000000000..517dff64af --- /dev/null +++ b/usr/src/test/zfs-tests/cmd/watch_dir/Makefile @@ -0,0 +1,19 @@ +# +# 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 2020 Joyent, Inc. +# + +PROG = watch_dir + +include $(SRC)/cmd/Makefile.cmd +include ../Makefile.subdirs diff --git a/usr/src/test/zfs-tests/cmd/watch_dir/watch_dir.c b/usr/src/test/zfs-tests/cmd/watch_dir/watch_dir.c new file mode 100644 index 0000000000..f6d8445162 --- /dev/null +++ b/usr/src/test/zfs-tests/cmd/watch_dir/watch_dir.c @@ -0,0 +1,151 @@ +/* + * 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 2020 Joyent, Inc. + */ + +/* + * This program watches a directory with portfs or inotify, exiting when the + * directory is removed. It is useful in tests that ensure that watching a + * directory does not prevent it from being used as a mount point. + */ +#include <limits.h> +#include <port.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/inotify.h> +#include <unistd.h> + +void +fail_usage(void) +{ + (void) fprintf(stderr, "Usage: watch <portfs|inotify> directory\n"); + exit(1); +} + +#define MAX_PES 8 + +void +watch_port(const char *path) +{ + int port; + struct file_obj fobj = {0}; + + if ((port = port_create()) < 0) { + perror("port_create"); + exit(1); + } + + fobj.fo_name = (char *)path; + for (;;) { + timespec_t ts = {300, 0}; + port_event_t pe; + + if (port_associate(port, PORT_SOURCE_FILE, (uintptr_t)&fobj, + 0, (char *)path) != 0) { + perror("port_associate"); + exit(1); + } + + if (port_get(port, &pe, &ts) != 0) { + perror("port_get"); + exit(1); + } + + if (pe.portev_events & FILE_DELETE) { + (void) printf("DELETE\t%s\n", path); + exit(0); + } + if (pe.portev_events & MOUNTEDOVER) { + (void) printf("MOUNTEDOVER\t%s\n", path); + } + } +} + +void +watch_inotify(const char *path) +{ + int in, wd; + struct inotify_event ev; + + if ((in = inotify_init()) < 0) { + perror("inotify_init"); + exit(1); + } + if ((wd = inotify_add_watch(in, path, IN_DELETE_SELF)) == -1) { + perror("inotify_add_watch"); + exit(1); + } + + for (;;) { + ssize_t cnt; + char evpath[PATH_MAX]; + + cnt = read(in, &ev, sizeof (ev)); + if (cnt != sizeof (ev)) { + (void) fprintf(stderr, + "read: expected %ld bytes got %ld\n", + sizeof (ev), cnt); + exit(1); + } + if (ev.len != 0) { + if (ev.len > sizeof (evpath)) { + (void) fprintf(stderr, "read: oversize " + "path (%u bytes)\n", ev.len); + exit(1); + } + cnt = read(in, evpath, ev.len); + if (cnt != ev.len) { + (void) fprintf(stderr, "read: expected %ld " + "bytes for path, got %ld\n", ev.len, cnt); + exit(1); + } + evpath[ev.len - 1] = '\0'; + } else { + evpath[0] = '\0'; + } + if (ev.mask & IN_DELETE_SELF) { + /* + * IN_DELETE_SELF events don't appear to include + * the path in the event. + */ + (void) printf("DELETE_SELF\n"); + exit(0); + } else { + (void) printf("EVENT_%08x\t%s\n", ev.mask, evpath); + } + + } +} + +int +main(int argc, char **argv) +{ + const char *watcher, *path; + + if (argc != 3) { + fail_usage(); + } + watcher = argv[1]; + path = argv[2]; + + if (strcmp(watcher, "portfs") == 0) { + watch_port(path); + } else if (strcmp(watcher, "inotify") == 0) { + watch_inotify(path); + } else { + fail_usage(); + } + + return (0); +} diff --git a/usr/src/test/zfs-tests/include/commands.cfg b/usr/src/test/zfs-tests/include/commands.cfg index c4769cbc71..dad9372554 100644 --- a/usr/src/test/zfs-tests/include/commands.cfg +++ b/usr/src/test/zfs-tests/include/commands.cfg @@ -198,4 +198,5 @@ export ZFSTEST_FILES='btree_test randwritecomp readmmap rename_dir - rm_lnkcnt_zero_file' + rm_lnkcnt_zero_file + watch_dir' diff --git a/usr/src/test/zfs-tests/runfiles/common.run b/usr/src/test/zfs-tests/runfiles/common.run index 82672045ce..f58eecec40 100644 --- a/usr/src/test/zfs-tests/runfiles/common.run +++ b/usr/src/test/zfs-tests/runfiles/common.run @@ -156,7 +156,8 @@ tests = ['zfs_create_001_pos', 'zfs_create_002_pos', 'zfs_create_003_pos', 'zfs_create_004_pos', 'zfs_create_005_pos', 'zfs_create_006_pos', 'zfs_create_007_pos', 'zfs_create_008_neg', 'zfs_create_009_neg', 'zfs_create_010_neg', 'zfs_create_011_pos', 'zfs_create_012_pos', - 'zfs_create_013_pos', 'zfs_create_encrypted', 'zfs_create_crypt_combos'] + 'zfs_create_013_pos', 'zfs_create_encrypted', 'zfs_create_crypt_combos', + 'zfs_create_dryrun', 'zfs_create_verbose'] tags = ['functional', 'cli_root', 'zfs_create'] [tests/functional/cli_root/zfs_destroy] @@ -194,7 +195,8 @@ tests = ['zfs_mount_001_pos', 'zfs_mount_002_pos', 'zfs_mount_003_pos', 'zfs_mount_007_pos', 'zfs_mount_008_pos', 'zfs_mount_009_neg', 'zfs_mount_010_neg', 'zfs_mount_011_neg', 'zfs_mount_012_neg', 'zfs_mount_all_001_pos', 'zfs_mount_all_fail', 'zfs_mount_all_mountpoints', - 'zfs_mount_encrypted'] + 'zfs_mount_encrypted', 'zfs_mount_watched_inotify', + 'zfs_mount_watched_portfs'] tags = ['functional', 'cli_root', 'zfs_mount'] [tests/functional/cli_root/zfs_program] diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_dryrun.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_dryrun.ksh new file mode 100644 index 0000000000..64b8296f46 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_dryrun.ksh @@ -0,0 +1,169 @@ +#!/bin/ksh -p +# +# 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 2019 Joyent, Inc. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib + +# +# DESCRIPTION: +# zfs create -n should perform basic sanity checking but should never create a +# dataset. If -v and/or -P are used, it should verbose about what would be +# created if sanity checks pass. +# +# STRATEGY: +# 1. Attempt to create a file system and a volume using various combinations of +# -n with -v and -P. +# + +verify_runnable "both" + +# +# Verifies that valid commands with -n and without -[vP]: +# - succeed +# - do not create a dataset +# - do not generate output +# +function dry_create_no_output +{ + typeset -a cmd=(zfs create -n "$@") + + log_note "$0: ${cmd[@]}" + log_must "${cmd[@]}" + datasetexists "$TESTPOOL/$TESTFS1" && + log_fail "$TESTPOOL/$TESTFS1 unexpectedly created by '${cmd[@]}'" + typeset out=$("${cmd[@]}" 2>&1) + [[ -z "$out" ]] || + log_fail "unexpected output '$out' from '${cmd[@]}'" +} + +# +# Verifies that commands with invalid properties or invalid property values +# - fail +# - do not create a dataset +# - generate a message on stderr +# +function dry_create_error +{ + typeset -a cmd=(zfs create -n "$@") + + log_note "$0: ${cmd[@]}" + log_mustnot "${cmd[@]}" + datasetexists "$TESTPOOL/$TESTFS1" && + log_fail "$TESTPOOL/$TESTFS1 unexpectedly created by '${cmd[@]}'" + typeset out=$("${cmd[@]}" 2>&1 >/dev/null) + [[ -z "$out" ]] && + log_fail "expected an error message but got none from '${cmd[@]}'" +} + +# +# Verifies that dry-run commands with parseable output +# - succeed +# - do not create datasets +# - generate parseable output on stdout +# - output matches expectations +# +function dry_create_parseable +{ + typeset -n exp=$1 + shift + typeset -a cmd=(zfs create -Pn "$@") + typeset ds=${cmd[${#cmd[@]} - 1]} + typeset out + typeset -a toks + typeset -a props + typeset found_create=false + + log_note "$0: ${cmd[@]}" + out=$("${cmd[@]}") + (( $? == 0 )) || + log_fail "unexpected failure getting stdout from '${cmd[@]}'" + datasetexists "$TESTPOOL/$TESTFS1" && + log_fail "$TESTPOOL/$TESTFS1 unexpectedly created by '${cmd[@]}'" + echo "$out" | while IFS=$'\t' read -A toks; do + log_note "verifying ${toks[@]}" + case ${toks[0]} in + create) + log_must test "${#toks[@]}" -eq 2 + log_must test "${toks[1]}" == "$ds" + found_create="yes, I found create" + ;; + property) + log_must test "${#toks[@]}" -eq 3 + typeset prop=${toks[1]} + typeset val=${toks[2]} + if [[ -z "${exp[$prop]}" ]]; then + log_fail "unexpectedly got property '$prop'" + fi + # We may not know the exact value a property will take + # on. This is the case for at least refreservation. + if [[ ${exp[$prop]} != "*" ]]; then + log_must test "${exp[$prop]}" == "$val" + fi + unset exp[$prop] + ;; + *) + log_fail "Unexpected line ${toks[@]}" + ;; + esac + done + + log_must test "$found_create" == "yes, I found create" + log_must test "extra props: ${!exp[@]}" == "extra props: " +} + +function cleanup +{ + if datasetexists "$TESTPOOL/$TESTFS1"; then + log_must zfs destroy -r "$TESTPOOL/$TESTFS1" + fi +} +log_onexit cleanup + +log_assert "zfs create -n creates nothing but can describe what would be" \ + "created" + +# Typical creations should succeed +dry_create_no_output "$TESTPOOL/$TESTFS1" +dry_create_no_output -V 10m "$TESTPOOL/$TESTFS1" +# It shouldn't do a space check right now +dry_create_no_output -V 100t "$TESTPOOL/$TESTFS1" +# It shouldn't create parent datasets either +dry_create_no_output -p "$TESTPOOL/$TESTFS1/$TESTFS2" +dry_create_no_output -pV 10m "$TESTPOOL/$TESTFS1/$TESTFS2" + +# Various invalid properties should be recognized and result in an error +dry_create_error -o nosuchprop=42 "$TESTPOOL/$TESTFS1" +dry_create_error -b 1234 -V 10m "$TESTPOOL/$TESTFS1" + +# Parseable output should be parseable. +typeset -A expect +expect=([compression]=on) +dry_create_parseable expect -o compression=on "$TESTPOOL/$TESTFS1" + +# Sparse volumes should not get a gratuitous refreservation +expect=([volblocksize]=4096 [volsize]=$((1024 * 1024 * 10))) +dry_create_parseable expect -b 4k -V 10m -s "$TESTPOOL/$TESTFS1" + +# Non-sparse volumes should have refreservation +expect=( + [volblocksize]=4096 + [volsize]=$((1024 * 1024 * 10)) + [refreservation]="*" +) +dry_create_parseable expect -b 4k -V 10m "$TESTPOOL/$TESTFS1" + +log_pass "zfs create -n creates nothing but can describe what would be" \ + "created" diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_watched_inotify.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_watched_inotify.ksh new file mode 100644 index 0000000000..0f181621e8 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_watched_inotify.ksh @@ -0,0 +1,74 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# 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. +# +# CDDL HEADER END +# + +# +# Copyright 2020 Joyent, Inc. +# + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION: +# 'zfs mount' should not get EBUSY due to inotify(5) watching a directory +# +# STRATEGY: +# 1. Create a directory +# 2. Start watching the directory with inotify(5). +# 3. Create a filesystem +# 4. Mount the filesystem at the directory created in step 1 +# 5. Destroy the filesystem +# 6. Remove the directory +# 7. Verify the watcher saw the directory removal +# + +verify_runnable "both" + +function cleanup +{ + datasetexists $TESTPOOL/$TESTFS1 && \ + log_must zfs destroy -f $TESTPOOL/$TESTFS1 + log_must rm -rf "$TESTDIR/mntpt" "$TESTDIR/watch_dir.log" +} + +log_onexit cleanup + +log_assert "'zfs mount' should not get EBUSY due to inotify(5) watching a directory" + +# 1. Create a directory. +log_must mkdir -p "$TESTDIR/mntpt" + +# 2. Start watching the directory with inotify(5). +watch_dir inotify $TESTDIR/mntpt > $TESTDIR/watch_dir.log & + +# 3. Create a filesystem +log_must zfs create $TESTPOOL/$TESTFS1 + +# 4. Mount the file system at the directory created in step 1 +log_must zfs set mountpoint=$TESTDIR/mntpt $TESTPOOL/$TESTFS1 + +# 5. Destroy the filesystem +log_must zfs destroy $TESTPOOL/$TESTFS1 + +# 6. Remove the directory. The corresponding inotify event will cause the +# watcher to exit. +log_must rmdir $TESTDIR/mntpt + +# 7. Verify the watcher saw the directory removal. This ensures that the watcher +# was watching the directory we are interested in. +wait +log_must grep -q DELETE_SELF $TESTDIR/watch_dir.log + +log_pass "'zfs mount' should not get EBUSY due to inotify(5) watching a directory" diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_watched_portfs.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_watched_portfs.ksh new file mode 100644 index 0000000000..3135203973 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_watched_portfs.ksh @@ -0,0 +1,74 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# 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. +# +# CDDL HEADER END +# + +# +# Copyright 2020 Joyent, Inc. +# + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION: +# 'zfs mount' should not get EBUSY due to portfs watching a directory +# +# STRATEGY: +# 1. Create a directory +# 2. Start watching the directory with port_associate +# 3. Create a filesystem +# 4. Mount the filesystem at the directory created in step 1 +# 5. Destroy the filesystem +# 6. Remove the directory +# 7. Verify the watcher saw the directory removal +# + +verify_runnable "both" + +function cleanup +{ + datasetexists $TESTPOOL/$TESTFS1 && \ + log_must zfs destroy -f $TESTPOOL/$TESTFS1 + log_must rm -rf "$TESTDIR/mntpt" "$TESTDIR/watch_dir.log" +} + +log_onexit cleanup + +log_assert "'zfs mount' should not get EBUSY due to portfs watching a directory" + +# 1. Create a directory. +log_must mkdir -p "$TESTDIR/mntpt" + +# 2. Start watching the directory with port_associate +watch_dir portfs $TESTDIR/mntpt > $TESTDIR/watch_dir.log & + +# 3. Create a filesystem +log_must zfs create $TESTPOOL/$TESTFS1 + +# 4. Mount the file system at the directory created in step 1 +log_must zfs set mountpoint=$TESTDIR/mntpt $TESTPOOL/$TESTFS1 + +# 5. Destroy the filesystem +log_must zfs destroy $TESTPOOL/$TESTFS1 + +# 6. Remove the directory. The corresponding portfs event will cause the +# watcher to exit. +log_must rmdir $TESTDIR/mntpt + +# 7. Verify the watcher saw the directory removal. This ensures that the watcher +# was watching the directory we are interested in. +wait +log_must grep -q DELETE.$TESTDIR/mntpt $TESTDIR/watch_dir.log + +log_pass "'zfs mount' should not get EBUSY due to portfs watching a directory" diff --git a/usr/src/test/zfs-tests/tests/functional/mmp/mmp.cfg b/usr/src/test/zfs-tests/tests/functional/mmp/mmp.cfg index 9f7e76e270..a58346dcae 100644 --- a/usr/src/test/zfs-tests/tests/functional/mmp/mmp.cfg +++ b/usr/src/test/zfs-tests/tests/functional/mmp/mmp.cfg @@ -15,6 +15,7 @@ # # Copyright (c) 2017 by Lawrence Livermore National Security, LLC. +# Copyright 2019 Joyent, Inc. # export PREV_UBER="$TEST_BASE_DIR/mmp-uber-prev.txt" diff --git a/usr/src/test/zfs-tests/tests/functional/nopwrite/nopwrite_sync.ksh b/usr/src/test/zfs-tests/tests/functional/nopwrite/nopwrite_sync.ksh index 415c8bdc5e..0ff8fcf97b 100644 --- a/usr/src/test/zfs-tests/tests/functional/nopwrite/nopwrite_sync.ksh +++ b/usr/src/test/zfs-tests/tests/functional/nopwrite/nopwrite_sync.ksh @@ -13,6 +13,7 @@ # # Copyright (c) 2012, 2016 by Delphix. All rights reserved. +# Copyright 2019 Joyent, Inc. # . $STF_SUITE/include/libtest.shlib @@ -42,12 +43,12 @@ log_assert "nopwrite works for sync writes" log_must zfs set compress=on $origin log_must zfs set checksum=sha256 $origin -gnu_dd if=/dev/urandom of=$TESTDIR/file bs=1024k count=$MEGS oflag=sync \ +dd if=/dev/urandom of=$TESTDIR/file bs=1024k count=$MEGS oflag=sync \ conv=notrunc >/dev/null 2>&1 || log_fail "dd into $TESTDIR/file failed." zfs snapshot $origin@a || log_fail "zfs snap failed" log_must zfs clone $origin@a $origin/clone -gnu_dd if=/$TESTDIR/file of=/$TESTDIR/clone/file bs=1024k count=$MEGS \ +dd if=/$TESTDIR/file of=/$TESTDIR/clone/file bs=1024k count=$MEGS \ oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed." log_must verify_nopwrite $origin $origin@a $origin/clone diff --git a/usr/src/test/zfs-tests/tests/functional/slog/slog.cfg b/usr/src/test/zfs-tests/tests/functional/slog/slog.cfg index 6a28880ade..17f28abaac 100644 --- a/usr/src/test/zfs-tests/tests/functional/slog/slog.cfg +++ b/usr/src/test/zfs-tests/tests/functional/slog/slog.cfg @@ -26,10 +26,11 @@ # # Copyright (c) 2013, 2015 by Delphix. All rights reserved. +# Copyright 2019 Joyent, Inc. # -export VDIR=/disk-slog -export VDIR2=/disk2-slog +export VDIR=/var/tmp/disk-slog +export VDIR2=/var/tmp/disk2-slog export VDEV="$VDIR/a $VDIR/b $VDIR/c" export SDEV="$VDIR/d" diff --git a/usr/src/test/zfs-tests/tests/functional/slog/slog_014_pos.ksh b/usr/src/test/zfs-tests/tests/functional/slog/slog_014_pos.ksh index efd876d554..63bd52288a 100644 --- a/usr/src/test/zfs-tests/tests/functional/slog/slog_014_pos.ksh +++ b/usr/src/test/zfs-tests/tests/functional/slog/slog_014_pos.ksh @@ -27,6 +27,7 @@ # # Copyright (c) 2013, 2018 by Delphix. All rights reserved. +# Copyright 2019 Joyent, Inc. # Copyright 2019 RackTop Systems. # |