diff options
author | jmmv <jmmv@FreeBSD.org> | 2014-04-27 01:15:10 +0000 |
---|---|---|
committer | jmmv <jmmv@FreeBSD.org> | 2014-04-27 01:15:10 +0000 |
commit | 1e4589b921fdaa1b1d2fc6b6ed016f1e0a01cb8f (patch) | |
tree | 94c86cf13dedabad5bdc68f6f227b843a5161343 /sbin | |
parent | 5b12da65bf9d40526ac9ca480d639bad3cd39cf6 (diff) | |
download | FreeBSD-src-1e4589b921fdaa1b1d2fc6b6ed016f1e0a01cb8f.zip FreeBSD-src-1e4589b921fdaa1b1d2fc6b6ed016f1e0a01cb8f.tar.gz |
MFC various moves of tools/regressions/ tests to the new infrastructure.
- r263220 Migrate tools/regression/sbin/ to the new tests layout.
- r263222 Add Makefile missed in r263220.
- r263226 Migrate tools/regression/{usr.bin/lastcomm,usr.sbin}/ to the new tests layout.
- r263227 Migrate most of tools/regression/usr.bin/ to the new tests layout.
- r263345 Expand tabs that sneaked in into spaces.
- r263346 Migrate tools/regression/usr.bin/make/ to the new tests layout.
- r263348 Add Makefiles missed in r263346.
- r263351 Migrate tools/regression/usr.bin/pkill/ to the new tests layout.
- r263388 Mark multi_test as requiring /usr/share/dict/words.
- r263814 Fix path to the run.pl script to let these tests run.
- r264742 Prevent building tests when bootstrapping make.
This is 'make tinderbox' clean.
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/Makefile | 4 | ||||
-rw-r--r-- | sbin/dhclient/Makefile | 6 | ||||
-rw-r--r-- | sbin/dhclient/tests/Makefile | 15 | ||||
-rw-r--r-- | sbin/dhclient/tests/fake.c | 64 | ||||
-rw-r--r-- | sbin/dhclient/tests/option-domain-search.c | 328 | ||||
-rw-r--r-- | sbin/growfs/Makefile | 6 | ||||
-rw-r--r-- | sbin/growfs/tests/Makefile | 7 | ||||
-rwxr-xr-x | sbin/growfs/tests/legacy_test.pl | 89 | ||||
-rw-r--r-- | sbin/mdconfig/Makefile | 6 | ||||
-rw-r--r-- | sbin/mdconfig/tests/Makefile | 13 | ||||
-rw-r--r-- | sbin/mdconfig/tests/legacy_test.sh | 47 | ||||
-rw-r--r-- | sbin/mdconfig/tests/mdconfig.test | 231 | ||||
-rw-r--r-- | sbin/mdconfig/tests/run.pl | 329 | ||||
-rw-r--r-- | sbin/tests/Makefile | 10 |
14 files changed, 1155 insertions, 0 deletions
diff --git a/sbin/Makefile b/sbin/Makefile index c6c3786..cad3219 100644 --- a/sbin/Makefile +++ b/sbin/Makefile @@ -114,6 +114,10 @@ SUBDIR+= quotacheck SUBDIR+= routed .endif +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include <bsd.arch.inc.mk> SUBDIR:= ${SUBDIR:O} diff --git a/sbin/dhclient/Makefile b/sbin/dhclient/Makefile index 74d1c4d..57c9211 100644 --- a/sbin/dhclient/Makefile +++ b/sbin/dhclient/Makefile @@ -31,6 +31,8 @@ # OF THE POSSIBILITY OF SUCH DAMAGE. # +.include <bsd.own.mk> + SRCS= dhclient.c clparse.c alloc.c dispatch.c hash.c bpf.c options.c \ tree.c conflex.c errwarn.c inet.c packet.c convert.c tables.c \ parse.c privsep.c @@ -44,4 +46,8 @@ LDADD= -lutil WARNS?= 2 +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include <bsd.prog.mk> diff --git a/sbin/dhclient/tests/Makefile b/sbin/dhclient/tests/Makefile new file mode 100644 index 0000000..b092eea --- /dev/null +++ b/sbin/dhclient/tests/Makefile @@ -0,0 +1,15 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/sbin/dhclient + +.PATH: ${.CURDIR}/.. + +PLAIN_TESTS_C= option-domain-search_test +SRCS.option-domain-search_test= alloc.c convert.c hash.c options.c \ + tables.c fake.c option-domain-search.c +CFLAGS.option-domain-search_test+= -I${.CURDIR}/.. +LDADD.option-domain-search_test= -lutil + +WARNS?= 2 + +.include <bsd.test.mk> diff --git a/sbin/dhclient/tests/fake.c b/sbin/dhclient/tests/fake.c new file mode 100644 index 0000000..c204d49 --- /dev/null +++ b/sbin/dhclient/tests/fake.c @@ -0,0 +1,64 @@ +/* $FreeBSD$ */ + +#include <setjmp.h> +#include <stdarg.h> +#include <stdio.h> + +#include "dhcpd.h" + +extern jmp_buf env; + +void +error(char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + + longjmp(env, 1); +} + +int +warning(char *fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + + /* + * The original warning() would return "ret" here. We do this to + * check warnings explicitely. + */ + longjmp(env, 1); +} + +int +note(char *fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + + return ret; +} + +void +bootp(struct packet *packet) +{ +} + +void +dhcp(struct packet *packet) +{ +} diff --git a/sbin/dhclient/tests/option-domain-search.c b/sbin/dhclient/tests/option-domain-search.c new file mode 100644 index 0000000..b79f9a5 --- /dev/null +++ b/sbin/dhclient/tests/option-domain-search.c @@ -0,0 +1,328 @@ +/* $FreeBSD$ */ + +#include <setjmp.h> +#include <stdlib.h> + +#include "dhcpd.h" + +jmp_buf env; + +void expand_domain_search(struct packet *packet); + +void +no_option_present() +{ + int ret; + struct option_data option; + struct packet p; + + option.data = NULL; + option.len = 0; + p.options[DHO_DOMAIN_SEARCH] = option; + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (p.options[DHO_DOMAIN_SEARCH].len != 0 || + p.options[DHO_DOMAIN_SEARCH].data != NULL) + abort(); +} + +void +one_domain_valid() +{ + int ret; + struct packet p; + struct option_data *option; + + char *data = "\007example\003org\0"; + char *expected = "example.org."; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 13; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (option->len != strlen(expected) || + strcmp(option->data, expected) != 0) + abort(); + + free(option->data); +} + +void +one_domain_truncated1() +{ + int ret; + struct option_data *option; + struct packet p; + + char *data = "\007example\003org"; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 12; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (ret != 1) + abort(); + + free(option->data); +} + +void +one_domain_truncated2() +{ + int ret; + struct option_data *option; + struct packet p; + + char *data = "\007ex"; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 3; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (ret != 1) + abort(); + + free(option->data); +} + +void +two_domains_valid() +{ + int ret; + struct packet p; + struct option_data *option; + + char *data = "\007example\003org\0\007example\003com\0"; + char *expected = "example.org. example.com."; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 26; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (option->len != strlen(expected) || + strcmp(option->data, expected) != 0) + abort(); + + free(option->data); +} + +void +two_domains_truncated1() +{ + int ret; + struct option_data *option; + struct packet p; + + char *data = "\007example\003org\0\007example\003com"; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 25; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (ret != 1) + abort(); + + free(option->data); +} + +void +two_domains_truncated2() +{ + int ret; + struct option_data *option; + struct packet p; + + char *data = "\007example\003org\0\007ex"; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 16; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (ret != 1) + abort(); + + free(option->data); +} + +void +two_domains_compressed() +{ + int ret; + struct packet p; + struct option_data *option; + + char *data = "\007example\003org\0\006foobar\xc0\x08"; + char *expected = "example.org. foobar.org."; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 22; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (option->len != strlen(expected) || + strcmp(option->data, expected) != 0) + abort(); + + free(option->data); +} + +void +two_domains_infloop() +{ + int ret; + struct packet p; + struct option_data *option; + + char *data = "\007example\003org\0\006foobar\xc0\x0d"; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 22; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (ret != 1) + abort(); + + free(option->data); +} + +void +two_domains_forwardptr() +{ + int ret; + struct packet p; + struct option_data *option; + + char *data = "\007example\003org\xc0\x0d\006foobar\0"; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 22; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (ret != 1) + abort(); + + free(option->data); +} + +void +two_domains_truncatedptr() +{ + int ret; + struct packet p; + struct option_data *option; + + char *data = "\007example\003org\0\006foobar\xc0"; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 21; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (ret != 1) + abort(); + + free(option->data); +} + +void +multiple_domains_valid() +{ + int ret; + struct packet p; + struct option_data *option; + + char *data = + "\007example\003org\0\002cl\006foobar\003com\0\002fr\xc0\x10"; + + char *expected = "example.org. cl.foobar.com. fr.foobar.com."; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 33; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (option->len != strlen(expected) || + strcmp(option->data, expected) != 0) + abort(); + + free(option->data); +} + +int +main(int argc, char *argv[]) +{ + + no_option_present(); + + one_domain_valid(); + one_domain_truncated1(); + one_domain_truncated2(); + + two_domains_valid(); + two_domains_truncated1(); + two_domains_truncated2(); + + two_domains_compressed(); + two_domains_infloop(); + two_domains_forwardptr(); + two_domains_truncatedptr(); + + multiple_domains_valid(); + + return (0); +} diff --git a/sbin/growfs/Makefile b/sbin/growfs/Makefile index f464ed7..58ce41d 100644 --- a/sbin/growfs/Makefile +++ b/sbin/growfs/Makefile @@ -6,6 +6,8 @@ #GFSDBG= +.include <bsd.own.mk> + .PATH: ${.CURDIR}/../mount PROG= growfs @@ -20,4 +22,8 @@ SRCS+= debug.c DPADD= ${LIBUTIL} LDADD= -lutil +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include <bsd.prog.mk> diff --git a/sbin/growfs/tests/Makefile b/sbin/growfs/tests/Makefile new file mode 100644 index 0000000..7a6a831 --- /dev/null +++ b/sbin/growfs/tests/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/sbin/growfs + +TAP_TESTS_PERL= legacy_test + +.include <bsd.test.mk> diff --git a/sbin/growfs/tests/legacy_test.pl b/sbin/growfs/tests/legacy_test.pl new file mode 100755 index 0000000..7316951 --- /dev/null +++ b/sbin/growfs/tests/legacy_test.pl @@ -0,0 +1,89 @@ +# $FreeBSD$ + +use strict; +use warnings; +use Test::More tests => 19; +use Fcntl qw(:DEFAULT :seek); + +use constant BLK => 512; +use constant BLKS_PER_MB => 2048; + +my $unit; +END { system "mdconfig -du$unit" if defined $unit }; + +sub setsize { + my ($partszMB, $unitszMB) = @_; + + open my $fd, "|-", "disklabel -R md$unit /dev/stdin" or die; + print $fd "a: ", ($partszMB * BLKS_PER_MB), " 0 4.2BSD 1024 8192\n"; + print $fd "c: ", ($unitszMB * BLKS_PER_MB), " 0 unused 0 0\n"; + close $fd; +} + +sub fill { + my ($start, $size, $content) = @_; + + my $content512 = $content x (int(512 / length $content) + 1); + substr($content512, 512) = ""; + sysopen my $fd, "/dev/md$unit", O_RDWR or die "/dev/md$unit: $!"; + seek($fd, $start * BLK, SEEK_SET); + while ($size) { + syswrite($fd, $content512) == 512 or die "write: $!"; + $size--; + } +} + +SKIP: { + skip "Cannot test without UID 0", 19 if $<; + + chomp(my $md = `mdconfig -s40m`); + like($md, qr/^md\d+$/, "Created $md with size 40m") or die; + $unit = substr $md, 2; + + for my $type (1..2) { + + initialise: { + ok(setsize(10, 40), "Sized ${md}a to 10m"); + system "newfs -O $type -U ${md}a >/dev/null"; + is($?, 0, "Initialised the filesystem on ${md}a as UFS$type"); + chomp(my @out = `fsck -tufs -y ${md}a`); + ok(!grep(/MODIFIED/, @out), "fsck says ${md}a is clean, " . + scalar(@out) . " lines of output"); + } + + extend20_zeroed: { + ok(setsize(20, 40), "Sized ${md}a to 20m"); + diag "Filling the extent with zeros"; + fill(10 * BLKS_PER_MB, 10 * BLKS_PER_MB, chr(0)); + my $out = `growfs -y ${md}a`; + is($?, 0, "Extended the filesystem on ${md}a") or print $out; + + my ($unallocated) = $out =~ m{\d+ sectors cannot be allocated}; + fill(30 * BLKS_PER_MB - $unallocated, $unallocated, chr(0)) + if $unallocated; + + chomp(my @out = `fsck -tufs -y ${md}a`); + ok(!grep(/MODIFIED/, @out), "fsck says ${md}a is clean, " . + scalar(@out) . " lines of output"); + } + + extend30_garbaged: { + ok(setsize(30, 40), "Sized ${md}a to 30m"); + diag "Filling the extent with garbage"; + fill(20 * BLKS_PER_MB, 10 * BLKS_PER_MB, chr(0xaa) . chr(0x55)); + my $out = `growfs -y ${md}a`; + is($?, 0, "Extended the filesystem on ${md}a") or print $out; + + my ($unallocated) = $out =~ m{\d+ sectors cannot be allocated}; + fill(30 * BLKS_PER_MB - $unallocated, $unallocated, chr(0)) + if $unallocated; + + chomp(my @out = `fsck -tufs -y ${md}a`); + ok(!grep(/MODIFIED/, @out), "fsck says ${md}a is clean, " . + scalar(@out) . " lines of output"); + } + } + + system "mdconfig -du$unit"; + undef $unit; +} diff --git a/sbin/mdconfig/Makefile b/sbin/mdconfig/Makefile index be8b1b5..4b9b940 100644 --- a/sbin/mdconfig/Makefile +++ b/sbin/mdconfig/Makefile @@ -1,9 +1,15 @@ # $FreeBSD$ +.include <bsd.own.mk> + PROG= mdconfig MAN= mdconfig.8 DPADD= ${LIBUTIL} ${LIBGEOM} ${LIBBSDXML} ${LIBSBUF} LDADD= -lutil -lgeom -lbsdxml -lsbuf +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include <bsd.prog.mk> diff --git a/sbin/mdconfig/tests/Makefile b/sbin/mdconfig/tests/Makefile new file mode 100644 index 0000000..17284bb --- /dev/null +++ b/sbin/mdconfig/tests/Makefile @@ -0,0 +1,13 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/sbin/mdconfig + +TAP_TESTS_SH= legacy_test +TAP_TESTS_SH_SED_legacy_test= 's,__PERL__,${TAP_PERL_INTERPRETER},g' +TEST_METADATA.legacy_test+= required_programs="${TAP_PERL_INTERPRETER}" + +FILESDIR= ${TESTSDIR} +FILES= mdconfig.test +FILES+= run.pl + +.include <bsd.test.mk> diff --git a/sbin/mdconfig/tests/legacy_test.sh b/sbin/mdconfig/tests/legacy_test.sh new file mode 100644 index 0000000..728224d --- /dev/null +++ b/sbin/mdconfig/tests/legacy_test.sh @@ -0,0 +1,47 @@ +#!/bin/sh +# +# Copyright (c) 2012 Edward Tomasz Napierała <trasz@FreeBSD.org> +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +# This is a wrapper script to run mdconfig.test. + +echo "1..1" + +if [ `whoami` != "root" ]; then + echo "ok 1 # skip You need to be root to run this test." + exit 0 +fi + +TESTDIR=$(dirname $(realpath $0)) + +__PERL__ -w -U $TESTDIR/run.pl $TESTDIR/mdconfig.test > /dev/null + +if [ $? -eq 0 ]; then + echo "ok 1" +else + echo "not ok 1" +fi diff --git a/sbin/mdconfig/tests/mdconfig.test b/sbin/mdconfig/tests/mdconfig.test new file mode 100644 index 0000000..65d3670 --- /dev/null +++ b/sbin/mdconfig/tests/mdconfig.test @@ -0,0 +1,231 @@ +# Copyright (c) 2012 Edward Tomasz Napierała <trasz@FreeBSD.org> +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +# This is a test for mdconfig(8) functionality. Run it as root: +# +# /usr/src/tools/regression/mdconfig/run /usr/src/tools/regression/mdconfig/mdconfig.test +# +# WARNING: Creates files in unsafe way. + +$ whoami +> root +$ umask 022 +$ truncate -s 1gb xxx + +$ mdconfig -l + +$ mdconfig -af xxx +> md0 + +# This awk thing is to strip the file path. +$ mdconfig -lv | awk '{ print $1, $2, $3 }' +> md0 vnode 1024M + +$ diskinfo -v /dev/md0 | expand +> /dev/md0 +> 512 # sectorsize +> 1073741824 # mediasize in bytes (1.0G) +> 2097152 # mediasize in sectors +> 0 # stripesize +> 0 # stripeoffset +> + +$ mdconfig -du 0 + +# Check different valid syntax variations: implicit -a. + +$ mdconfig xxx +> md0 + +$ mdconfig -lv | awk '{ print $1, $2, $3 }' +> md0 vnode 1024M + +$ diskinfo -v /dev/md0 | expand +> /dev/md0 +> 512 # sectorsize +> 1073741824 # mediasize in bytes (1.0G) +> 2097152 # mediasize in sectors +> 0 # stripesize +> 0 # stripeoffset +> + +$ mdconfig -du 0 + +# Explicit -t vnode. + +$ mdconfig -a -t vnode -f xxx +> md0 + +$ mdconfig -lv | awk '{ print $1, $2, $3 }' +> md0 vnode 1024M + +$ diskinfo -v /dev/md0 | expand +> /dev/md0 +> 512 # sectorsize +> 1073741824 # mediasize in bytes (1.0G) +> 2097152 # mediasize in sectors +> 0 # stripesize +> 0 # stripeoffset +> + +$ mdconfig -du 0 + +# Size for vnodes - smaller than the actual file. + +$ mdconfig -a -t vnode -f xxx -s 128m +> md0 + +$ mdconfig -lv | awk '{ print $1, $2, $3 }' +> md0 vnode 128M + +$ diskinfo -v /dev/md0 | expand +> /dev/md0 +> 512 # sectorsize +> 134217728 # mediasize in bytes (128M) +> 262144 # mediasize in sectors +> 0 # stripesize +> 0 # stripeoffset +> + +$ mdconfig -du 0 + +# Size for vnodes - larger than the actual file. + +$ mdconfig -a -t vnode -f xxx -s 128g +> md0 + +$ mdconfig -lv | awk '{ print $1, $2, $3 }' +> md0 vnode 128G + +$ diskinfo -v /dev/md0 | expand +> /dev/md0 +> 512 # sectorsize +> 137438953472 # mediasize in bytes (128G) +> 268435456 # mediasize in sectors +> 0 # stripesize +> 0 # stripeoffset +> + +$ mdconfig -du 0 + +# Sector size for vnodes. + +$ mdconfig -a -t vnode -f xxx -S 2048 +> md0 + +$ mdconfig -lv | awk '{ print $1, $2, $3 }' +> md0 vnode 1024M + +$ diskinfo -v /dev/md0 | expand +> /dev/md0 +> 2048 # sectorsize +> 1073741824 # mediasize in bytes (1.0G) +> 524288 # mediasize in sectors +> 0 # stripesize +> 0 # stripeoffset +> + +$ mdconfig -du 0 + +# Malloc type. + +$ mdconfig -a -t malloc -s 1g +> md0 + +$ mdconfig -lv | awk '{ print $1, $2, $3 }' +> md0 malloc 1024M + +$ diskinfo -v /dev/md0 | expand +> /dev/md0 +> 512 # sectorsize +> 1073741824 # mediasize in bytes (1.0G) +> 2097152 # mediasize in sectors +> 0 # stripesize +> 0 # stripeoffset +> + +$ mdconfig -du 0 + +# Swap type. + +$ mdconfig -a -t swap -s 1g +> md0 + +$ mdconfig -lv | awk '{ print $1, $2, $3 }' +> md0 swap 1024M + +$ diskinfo -v /dev/md0 | expand +> /dev/md0 +> 512 # sectorsize +> 1073741824 # mediasize in bytes (1.0G) +> 2097152 # mediasize in sectors +> 0 # stripesize +> 0 # stripeoffset +> + +$ mdconfig -du 0 + +# Attaching with a specific unit number. + +$ mdconfig -as 1g -u 42 + +$ mdconfig -lv | awk '{ print $1, $2, $3 }' +> md42 swap 1024M + +$ diskinfo -v /dev/md42 | expand +> /dev/md42 +> 512 # sectorsize +> 1073741824 # mediasize in bytes (1.0G) +> 2097152 # mediasize in sectors +> 0 # stripesize +> 0 # stripeoffset +> + +$ mdconfig -du 42 + +# Querying. + +$ mdconfig -as 1g +> md0 +$ mdconfig -as 2g -u 42 + +$ mdconfig -lv | awk '{ print $1, $2, $3 }' +> md0 swap 1024M +> md42 swap 2048M + +$ mdconfig -lvu 0 | awk '{ print $1, $2, $3 }' +> md0 swap 1024M + +$ mdconfig -lvu 42 | awk '{ print $1, $2, $3 }' +> md42 swap 2048M + +$ mdconfig -lvu 24 | awk '{ print $1, $2, $3 }' + +$ mdconfig -du 42 +$ mdconfig -du 0 + +$ rm xxx diff --git a/sbin/mdconfig/tests/run.pl b/sbin/mdconfig/tests/run.pl new file mode 100644 index 0000000..383f47e --- /dev/null +++ b/sbin/mdconfig/tests/run.pl @@ -0,0 +1,329 @@ +#!/usr/bin/perl -w -U + +# Copyright (c) 2007, 2008 Andreas Gruenbacher. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions, and the following disclaimer, +# without modification, immediately at the beginning of the file. +# 2. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# Alternatively, this software may be distributed under the terms of the +# GNU Public License ("GPL"). +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +# +# Possible improvements: +# +# - distinguish stdout and stderr output +# - add environment variable like assignments +# - run up to a specific line +# - resume at a specific line +# + +use strict; +use FileHandle; +use Getopt::Std; +use POSIX qw(isatty setuid getcwd); +use vars qw($opt_l $opt_v); + +no warnings qw(taint); + +$opt_l = ~0; # a really huge number +getopts('l:v'); + +my ($OK, $FAILED) = ("ok", "failed"); +if (isatty(fileno(STDOUT))) { + $OK = "\033[32m" . $OK . "\033[m"; + $FAILED = "\033[31m\033[1m" . $FAILED . "\033[m"; +} + +sub exec_test($$); +sub process_test($$$$); + +my ($prog, $in, $out) = ([], [], []); +my $prog_line = 0; +my ($tests, $failed) = (0,0); +my $lineno; +my $width = ($ENV{COLUMNS} || 80) >> 1; + +for (;;) { + my $line = <>; $lineno++; + if (defined $line) { + # Substitute %VAR and %{VAR} with environment variables. + $line =~ s[%(\w+)][$ENV{$1}]eg; + $line =~ s[%{(\w+)}][$ENV{$1}]eg; + } + if (defined $line) { + if ($line =~ s/^\s*< ?//) { + push @$in, $line; + } elsif ($line =~ s/^\s*> ?//) { + push @$out, $line; + } else { + process_test($prog, $prog_line, $in, $out); + last if $prog_line >= $opt_l; + + $prog = []; + $prog_line = 0; + } + if ($line =~ s/^\s*\$ ?//) { + $prog = [ map { s/\\(.)/$1/g; $_ } split /(?<!\\)\s+/, $line ]; + $prog_line = $lineno; + $in = []; + $out = []; + } + } else { + process_test($prog, $prog_line, $in, $out); + last; + } +} + +my $status = sprintf("%d commands (%d passed, %d failed)", + $tests, $tests-$failed, $failed); +if (isatty(fileno(STDOUT))) { + if ($failed) { + $status = "\033[31m\033[1m" . $status . "\033[m"; + } else { + $status = "\033[32m" . $status . "\033[m"; + } +} +print $status, "\n"; +exit $failed ? 1 : 0; + + +sub process_test($$$$) { + my ($prog, $prog_line, $in, $out) = @_; + + return unless @$prog; + + my $p = [ @$prog ]; + print "[$prog_line] \$ ", join(' ', + map { s/\s/\\$&/g; $_ } @$p), " -- "; + my $result = exec_test($prog, $in); + my @good = (); + my $nmax = (@$out > @$result) ? @$out : @$result; + for (my $n=0; $n < $nmax; $n++) { + my $use_re; + if (defined $out->[$n] && $out->[$n] =~ /^~ /) { + $use_re = 1; + $out->[$n] =~ s/^~ //g; + } + + if (!defined($out->[$n]) || !defined($result->[$n]) || + (!$use_re && $result->[$n] ne $out->[$n]) || + ( $use_re && $result->[$n] !~ /^$out->[$n]/)) { + push @good, ($use_re ? '!~' : '!='); + } + else { + push @good, ($use_re ? '=~' : '=='); + } + } + my $good = !(grep /!/, @good); + $tests++; + $failed++ unless $good; + print $good ? $OK : $FAILED, "\n"; + if (!$good || $opt_v) { + for (my $n=0; $n < $nmax; $n++) { + my $l = defined($out->[$n]) ? $out->[$n] : "~"; + chomp $l; + my $r = defined($result->[$n]) ? $result->[$n] : "~"; + chomp $r; + print sprintf("%-" . ($width-3) . "s %s %s\n", + $r, $good[$n], $l); + } + } +} + + +sub su($) { + my ($user) = @_; + + $user ||= "root"; + + my ($login, $pass, $uid, $gid) = getpwnam($user) + or return [ "su: user $user does not exist\n" ]; + my @groups = (); + my $fh = new FileHandle("/etc/group") + or return [ "opening /etc/group: $!\n" ]; + while (<$fh>) { + chomp; + my ($group, $passwd, $gid, $users) = split /:/; + foreach my $u (split /,/, $users) { + push @groups, $gid + if ($user eq $u); + } + } + $fh->close; + + my $groups = join(" ", ($gid, $gid, @groups)); + #print STDERR "[[$groups]]\n"; + $! = 0; # reset errno + $> = 0; + $( = $gid; + $) = $groups; + if ($!) { + return [ "su: $!\n" ]; + } + if ($uid != 0) { + $> = $uid; + #$< = $uid; + if ($!) { + return [ "su: $prog->[1]: $!\n" ]; + } + } + #print STDERR "[($>,$<)($(,$))]"; + return []; +} + + +sub sg($) { + my ($group) = @_; + + my $gid = getgrnam($group) + or return [ "sg: group $group does not exist\n" ]; + my %groups = map { $_ eq $gid ? () : ($_ => 1) } (split /\s/, $)); + + #print STDERR "<<", join("/", keys %groups), ">>\n"; + my $groups = join(" ", ($gid, $gid, keys %groups)); + #print STDERR "[[$groups]]\n"; + $! = 0; # reset errno + if ($> != 0) { + my $uid = $>; + $> = 0; + $( = $gid; + $) = $groups; + $> = $uid; + } else { + $( = $gid; + $) = $groups; + } + if ($!) { + return [ "sg: $!\n" ]; + } + print STDERR "[($>,$<)($(,$))]"; + return []; +} + + +sub exec_test($$) { + my ($prog, $in) = @_; + local (*IN, *IN_DUP, *IN2, *OUT_DUP, *OUT, *OUT2); + my $needs_shell = (join('', @$prog) =~ /[][|<>"'`\$\*\?]/); + + if ($prog->[0] eq "umask") { + umask oct $prog->[1]; + return []; + } elsif ($prog->[0] eq "cd") { + if (!chdir $prog->[1]) { + return [ "chdir: $prog->[1]: $!\n" ]; + } + $ENV{PWD} = getcwd; + return []; + } elsif ($prog->[0] eq "su") { + return su($prog->[1]); + } elsif ($prog->[0] eq "sg") { + return sg($prog->[1]); + } elsif ($prog->[0] eq "export") { + my ($name, $value) = split /=/, $prog->[1]; + # FIXME: need to evaluate $value, so that things like this will work: + # export dir=$PWD/dir + $ENV{$name} = $value; + return []; + } elsif ($prog->[0] eq "unset") { + delete $ENV{$prog->[1]}; + return []; + } + + pipe *IN2, *OUT + or die "Can't create pipe for reading: $!"; + open *IN_DUP, "<&STDIN" + or *IN_DUP = undef; + open *STDIN, "<&IN2" + or die "Can't duplicate pipe for reading: $!"; + close *IN2; + + open *OUT_DUP, ">&STDOUT" + or die "Can't duplicate STDOUT: $!"; + pipe *IN, *OUT2 + or die "Can't create pipe for writing: $!"; + open *STDOUT, ">&OUT2" + or die "Can't duplicate pipe for writing: $!"; + close *OUT2; + + *STDOUT->autoflush(); + *OUT->autoflush(); + + $SIG{CHLD} = 'IGNORE'; + + if (fork()) { + # Server + if (*IN_DUP) { + open *STDIN, "<&IN_DUP" + or die "Can't duplicate STDIN: $!"; + close *IN_DUP + or die "Can't close STDIN duplicate: $!"; + } + open *STDOUT, ">&OUT_DUP" + or die "Can't duplicate STDOUT: $!"; + close *OUT_DUP + or die "Can't close STDOUT duplicate: $!"; + + foreach my $line (@$in) { + #print "> $line"; + print OUT $line; + } + close *OUT + or die "Can't close pipe for writing: $!"; + + my $result = []; + while (<IN>) { + #print "< $_"; + if ($needs_shell) { + s#^/bin/sh: line \d+: ##; + } + push @$result, $_; + } + return $result; + } else { + # Client + $< = $>; + close IN + or die "Can't close read end for input pipe: $!"; + close OUT + or die "Can't close write end for output pipe: $!"; + close OUT_DUP + or die "Can't close STDOUT duplicate: $!"; + local *ERR_DUP; + open ERR_DUP, ">&STDERR" + or die "Can't duplicate STDERR: $!"; + open STDERR, ">&STDOUT" + or die "Can't join STDOUT and STDERR: $!"; + + if ($needs_shell) { + exec ('/bin/sh', '-c', join(" ", @$prog)); + } else { + exec @$prog; + } + print STDERR $prog->[0], ": $!\n"; + exit; + } +} + diff --git a/sbin/tests/Makefile b/sbin/tests/Makefile new file mode 100644 index 0000000..a298f87 --- /dev/null +++ b/sbin/tests/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ + +.include <bsd.own.mk> + +TESTSDIR= ${TESTSBASE}/sbin + +.PATH: ${.CURDIR:H:H}/tests +KYUAFILE= yes + +.include <bsd.test.mk> |