diff options
Diffstat (limited to 'tests/df')
-rwxr-xr-x | tests/df/df-P.sh | 37 | ||||
-rwxr-xr-x | tests/df/df-output.sh | 140 | ||||
-rwxr-xr-x | tests/df/df-symlink.sh | 44 | ||||
-rwxr-xr-x | tests/df/header.sh | 28 | ||||
-rwxr-xr-x | tests/df/no-mtab-status.sh | 125 | ||||
-rwxr-xr-x | tests/df/over-mount-device.sh | 59 | ||||
-rwxr-xr-x | tests/df/problematic-chars.sh | 65 | ||||
-rwxr-xr-x | tests/df/skip-duplicates.sh | 191 | ||||
-rwxr-xr-x | tests/df/skip-rootfs.sh | 53 | ||||
-rwxr-xr-x | tests/df/total-unprocessed.sh | 44 | ||||
-rwxr-xr-x | tests/df/total-verify.sh | 67 | ||||
-rwxr-xr-x | tests/df/unreadable.sh | 32 |
12 files changed, 885 insertions, 0 deletions
diff --git a/tests/df/df-P.sh b/tests/df/df-P.sh new file mode 100755 index 0000000..7b4c6e6 --- /dev/null +++ b/tests/df/df-P.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# Ensure that df -P is not affected by BLOCK_SIZE settings + +# Copyright (C) 2007-2020 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src +print_ver_ df + + + df -P . > t1 || fail=1 +BLOCK_SIZE=1M df -P . > t2 || fail=1 + +# Since disk utilization may be changing, compare only df's header line. +# That records the block size. E.g., for "1M", it would be: +# Filesystem 1048576-blocks Used Available Capacity Mounted on +# while for 1K, it would be +# Filesystem 1024-blocks Used Available Capacity Mounted on + +head -n1 t1 > exp || fail=1 +head -n1 t2 > out || fail=1 + +compare exp out || fail=1 + +Exit $fail diff --git a/tests/df/df-output.sh b/tests/df/df-output.sh new file mode 100755 index 0000000..6d63d66 --- /dev/null +++ b/tests/df/df-output.sh @@ -0,0 +1,140 @@ +#!/bin/sh +# Exercise df's --output option. + +# Copyright (C) 2012-2020 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src +print_ver_ df + +# Ensure that --output is mutually exclusive with -i, -P, and -T. +# Ensure that this limitation is not depending on the order of options. +cat <<\EOF > exp || framework_failure_ +df: options OPT and --output are mutually exclusive +Try 'df --help' for more information. +EOF + +df -i --output '.' 2>out && fail=1 +sed 's/ -i / OPT /' out > out2 +compare exp out2 || fail=1 + +df --output -i '.' 2>out && fail=1 +sed 's/ -i / OPT /' out > out2 +compare exp out2 || fail=1 + +df -P --output '.' 2>out && fail=1 +sed 's/ -P / OPT /' out > out2 +compare exp out2 || fail=1 + +df --output -P '.' 2>out && fail=1 +sed 's/ -P / OPT /' out > out2 +compare exp out2 || fail=1 + +df -T --output '.' 2>out && fail=1 +sed 's/ -T / OPT /' out > out2 +compare exp out2 || fail=1 + +df --output -T '.' 2>out && fail=1 +sed 's/ -T / OPT /' out > out2 +compare exp out2 || fail=1 + +# Ensure that each field is only used once for the --output argument. +cat <<\EOF > exp || framework_failure_ +df: option --output: field 'target' used more than once +Try 'df --help' for more information. +EOF + +df --output=target,source,target '.' 2>out && fail=1 +compare exp out || fail=1 + +# Ensure that this limitation also works for splitted --output options. +df --out=target,source --out=target '.' 2>out && fail=1 +compare exp out || fail=1 + +# Ensure that the full output includes all fields, and +# that --o (without argument) is identical to the full list. + +cat <<\EOF > exp || framework_failure_ +Filesystem Type Inodes IUsed IFree IUse% Size Used Avail Use% File Mounted on +EOF + +df -h --o=source,fstype,itotal,iused,iavail,ipcent \ + --o=size,used,avail,pcent,file,target '.' >out || fail=1 +sed -e '1 { + s/ [ ]*/ /g + q + }' out > out2 +compare exp out2 || fail=1 + +df -h --output '.' >out || fail=1 +sed -e '1 { + s/ [ ]*/ /g + q + }' out > out2 +compare exp out2 || fail=1 + +# Ensure that --output indicates the block size +# when not using --human-readable +cat <<\EOF > exp || framework_failure_ +1K-blocks +EOF + +df -B1K --output=size '.' >out || fail=1 +sed -e '1 { + s/ *// + q + }' out > out2 +compare exp out2 || fail=1 + +# Ensure that the grand total line now contains a "-" in the TARGET field ... +cat <<\EOF > exp || framework_failure_ +- +EOF + +df --output=source,target --total '.' >out || fail=1 +sed -n -e '3 { + s/^total[ ]*// + p + q + }' out > out2 +compare exp out2 || fail=1 + +# ... but it should read "total" if there is no SOURCE field. +cat <<\EOF > exp || framework_failure_ +total +EOF + +df --output=target --total '.' >out || fail=1 +sed -n -e '3 { + p + q + }' out > out2 +compare exp out2 || fail=1 + +# Ensure that --output is mentioned in the usage. +df --help > out || fail=1 +grep ' --output' out >/dev/null || { fail=1; cat out; } + +# Ensure that the FILE field contains the argument. +cat <<\EOF > exp || framework_failure_ +. +exp +EOF + +df --output=file '.' exp >out || fail=1 +sed '1d' out > out2 +compare exp out2 || fail=1 + +Exit $fail diff --git a/tests/df/df-symlink.sh b/tests/df/df-symlink.sh new file mode 100755 index 0000000..a1d59a8 --- /dev/null +++ b/tests/df/df-symlink.sh @@ -0,0 +1,44 @@ +#!/bin/sh +# Ensure that df dereferences symlinks to disk nodes + +# Copyright (C) 2013-2020 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src +print_ver_ df + +disk=$(df --out=source '.' | tail -n1) || + skip_ "cannot determine '.' file system" + +ln -s "$disk" symlink || framework_failure_ + +df --out=source,target "$disk" > exp || skip_ "cannot get info for $disk" +df --out=source,target symlink > out || fail=1 +compare exp out || fail=1 + +# Ensure we output the same values for device nodes and '.' +# This was not the case in coreutil-8.22 on systems +# where the device in the mount list was a symlink itself. +# I.e., '.' => /dev/mapper/fedora-home -> /dev/dm-2 +# Restrict this test to systems with a 1:1 mapping between +# source and target. This excludes for example BTRFS sub-volumes. +if test "$(df --output=source | grep -F "$disk" | wc -l)" = 1; then + df --out=source,target '.' > out || fail=1 + compare exp out || fail=1 +fi + +test "$fail" = 1 && dump_mount_list_ + +Exit $fail diff --git a/tests/df/header.sh b/tests/df/header.sh new file mode 100755 index 0000000..2462b15 --- /dev/null +++ b/tests/df/header.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# Ensure that "df ." outputs a header. + +# Copyright (C) 2006-2020 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src +print_ver_ df + +case $(df .) in +*' +'*) ;; +*) fail=1;; +esac + +Exit $fail diff --git a/tests/df/no-mtab-status.sh b/tests/df/no-mtab-status.sh new file mode 100755 index 0000000..62adccc --- /dev/null +++ b/tests/df/no-mtab-status.sh @@ -0,0 +1,125 @@ +#!/bin/sh +# Test df's behaviour when the mount list cannot be read. +# This test is skipped on systems that lack LD_PRELOAD support; that's fine. + +# Copyright (C) 2012-2020 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src +print_ver_ df +require_gcc_shared_ + +# Protect against inaccessible remote mounts etc. +timeout 10 df || skip_ "df fails" + +grep '^#define HAVE_MNTENT_H 1' $CONFIG_HEADER > /dev/null \ + || skip_ "no mntent.h available to confirm the interface" + +grep '^#define HAVE_GETMNTENT 1' $CONFIG_HEADER > /dev/null \ + || skip_ "getmntent is not used on this system" + +# Simulate "mtab" failure. +cat > k.c <<EOF || framework_failure_ +#define _GNU_SOURCE +#include <stdio.h> +#include <errno.h> +#include <mntent.h> +#include <string.h> +#include <dlfcn.h> + +#define STREQ(a, b) (strcmp (a, b) == 0) + +FILE* fopen(const char *path, const char *mode) +{ + static FILE* (*fopen_func)(char const *, char const *); + + /* get reference to original (libc provided) fopen */ + if (!fopen_func) + { + fopen_func = (FILE*(*)(char const *, char const *)) + dlsym(RTLD_NEXT, "fopen"); + if (!fopen_func) + { + fprintf (stderr, "Failed to find fopen()\n"); + errno = ESRCH; + return NULL; + } + } + + /* Returning ENOENT here will get read_file_system_list() + to fall back to using getmntent() below. */ + if (STREQ (path, "/proc/self/mountinfo")) + { + errno = ENOENT; + return NULL; + } + else + return fopen_func(path, mode); +} + +struct mntent *getmntent (FILE *fp) +{ + /* Prove that LD_PRELOAD works. */ + static int done = 0; + if (!done) + { + fclose (fopen ("x", "w")); + ++done; + } + /* Now simulate the failure. */ + errno = ENOENT; + return NULL; +} +EOF + +# Then compile/link it: +gcc_shared_ k.c k.so \ + || framework_failure_ 'failed to build shared library' + +cleanup_() { unset LD_PRELOAD; } + +export LD_PRELOAD=$LD_PRELOAD:./k.so + +# Test if LD_PRELOAD works: +df 2>/dev/null +test -f x || skip_ "internal test failure: maybe LD_PRELOAD doesn't work?" + +# These tests are supposed to succeed: +df '.' || fail=1 +df -i '.' || fail=1 +df -T '.' || fail=1 +df -Ti '.' || fail=1 +df --total '.' || fail=1 + +# These tests are supposed to fail: +returns_ 1 df || fail=1 +returns_ 1 df -i || fail=1 +returns_ 1 df -T || fail=1 +returns_ 1 df -Ti || fail=1 +returns_ 1 df --total || fail=1 + +returns_ 1 df -a || fail=1 +returns_ 1 df -a '.' || fail=1 + +returns_ 1 df -l || fail=1 +returns_ 1 df -l '.' || fail=1 + +returns_ 1 df -t hello || fail=1 +returns_ 1 df -t hello '.' || fail=1 + +returns_ 1 df -x hello || fail=1 +returns_ 1 df -x hello '.' || fail=1 + +Exit $fail diff --git a/tests/df/over-mount-device.sh b/tests/df/over-mount-device.sh new file mode 100755 index 0000000..524e119 --- /dev/null +++ b/tests/df/over-mount-device.sh @@ -0,0 +1,59 @@ +#!/bin/sh +# Ensure that df /dev/loop0 errors out if overmounted by another device + +# Copyright (C) 2014-2020 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src +print_ver_ df +require_root_ + +cwd=$(pwd) +cleanup_() { cd /; umount "$cwd/mnt"; umount "$cwd/mnt"; } + +skip=0 + +# Create 2 file systems +for i in 1 2; do + dd if=/dev/zero of=blob$i bs=8192 count=200 > /dev/null 2>&1 \ + || skip=1 + mkfs -t ext2 -F blob$i \ + || skip_ "failed to create ext2 file system" +done + +# Mount both at the same place (eclipsing the first) +mkdir mnt || skip=1 +mount -oloop blob1 mnt || skip=1 +eclipsed_dev=$(df --o=source mnt | tail -n1) || skip=1 +mount -oloop blob2 mnt || skip=1 + +test $skip = 1 \ + && skip_ "insufficient mount/ext2 support" + +df . || skip_ "failed to lookup the device for the current dir" + +echo "df: cannot access '$eclipsed_dev': over-mounted by another device" > exp + +# We should get an error for the eclipsed device and continue +df $eclipsed_dev . > out 2> err && fail=1 + +# header and single entry in output +test $(wc -l < out) = 2 || fail=1 + +compare exp err || fail=1 + +test "$fail" = 1 && dump_mount_list_ + +Exit $fail diff --git a/tests/df/problematic-chars.sh b/tests/df/problematic-chars.sh new file mode 100755 index 0000000..c440c8d --- /dev/null +++ b/tests/df/problematic-chars.sh @@ -0,0 +1,65 @@ +#!/bin/sh +# Ensure that df outputs one line per entry + +# Copyright (C) 2012-2020 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src +print_ver_ df printf +require_root_ + + +# Ensure a new line in a mount point only outputs a single line + +mnt='mount +point' + +cwd=$(pwd) +cleanup_() { umount "$cwd/$mnt"; } + +skip=0 +# Create a file system, then mount it. +dd if=/dev/zero of=blob bs=8192 count=200 > /dev/null 2>&1 \ + || skip=1 +mkdir "$mnt" || skip=1 +mkfs -t ext2 -F blob \ + || skip_ "failed to create ext2 file system" +mount -oloop blob "$mnt" || skip=1 +test $skip = 1 \ + && skip_ "insufficient mount/ext2 support" +test $(df "$mnt" | wc -l) = 2 || fail=1 +test "$fail" = 1 && dump_mount_list_ + + +# Ensure mount points not matching the current user encoding are output + +unset LC_ALL +f=$LOCALE_FR_UTF8 +: ${LOCALE_FR_UTF8=none} +if test "$LOCALE_FR_UTF8" != "none"; then + + cleanup_ || framework_failure_ + + # Create a non UTF8 mount point + mnt="$(env printf 'm\xf3unt p\xf3int')" + mkdir "$mnt" || framework_failure_ + mount -oloop blob "$mnt" || skip_ "unable to mount $mnt" + + LC_ALL=$f df --output=target "$mnt" > df.out || fail=1 + test "$(basename "$(tail -n1 df.out)")" = "$mnt" || fail=1 +fi + + +Exit $fail diff --git a/tests/df/skip-duplicates.sh b/tests/df/skip-duplicates.sh new file mode 100755 index 0000000..8730948 --- /dev/null +++ b/tests/df/skip-duplicates.sh @@ -0,0 +1,191 @@ +#!/bin/sh +# Test df's behavior when the mount list contains duplicate entries. +# This test is skipped on systems that lack LD_PRELOAD support; that's fine. + +# Copyright (C) 2012-2020 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src +print_ver_ df +require_gcc_shared_ + +# We use --local here so as to not activate +# potentially very many remote mounts. +df --local --output=target >LOCAL_FS || skip_ 'df fails' +grep '^/$' LOCAL_FS || skip_ 'no root file system found' + +# Get real targets to substitute for /NONROOT and /REMOTE below. +export CU_NONROOT_FS=$(grep /. LOCAL_FS | head -n1) +export CU_REMOTE_FS=$(grep /. LOCAL_FS | tail -n+2 | head -n1) + +unique_entries=1 +test -z "$CU_NONROOT_FS" || unique_entries=$(expr $unique_entries + 1) +test -z "$CU_REMOTE_FS" || unique_entries=$(expr $unique_entries + 2) + +grep '^#define HAVE_MNTENT_H 1' $CONFIG_HEADER > /dev/null \ + || skip_ "no mntent.h available to confirm the interface" + +grep '^#define HAVE_GETMNTENT 1' $CONFIG_HEADER > /dev/null \ + || skip_ "getmntent is not used on this system" + +# Simulate an mtab file to test various cases. +cat > k.c <<EOF || framework_failure_ +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <mntent.h> +#include <string.h> +#include <dlfcn.h> + +#define STREQ(a, b) (strcmp (a, b) == 0) + +FILE* fopen(const char *path, const char *mode) +{ + static FILE* (*fopen_func)(char const *, char const *); + + /* get reference to original (libc provided) fopen */ + if (!fopen_func) + { + fopen_func = (FILE*(*)(char const *, char const *)) + dlsym(RTLD_NEXT, "fopen"); + if (!fopen_func) + { + fprintf (stderr, "Failed to find fopen()\n"); + errno = ESRCH; + return NULL; + } + } + + /* Returning ENOENT here will get read_file_system_list() + to fall back to using getmntent() below. */ + if (STREQ (path, "/proc/self/mountinfo")) + { + errno = ENOENT; + return NULL; + } + else + return fopen_func(path, mode); +} + +#define STREQ(a, b) (strcmp (a, b) == 0) + +struct mntent *getmntent (FILE *fp) +{ + static char *nonroot_fs; + static char *remote_fs; + static int done; + + /* Prove that LD_PRELOAD works. */ + if (!done) + { + fclose (fopen ("x", "w")); + ++done; + } + + static struct mntent mntents[] = { + {.mnt_fsname="/short", .mnt_dir="/invalid/mount/dir", .mnt_opts=""}, + {.mnt_fsname="fsname", .mnt_dir="/", .mnt_opts=""}, + {.mnt_fsname="/fsname", .mnt_dir="/.", .mnt_opts=""}, + {.mnt_fsname="/fsname", .mnt_dir="/", .mnt_opts=""}, + {.mnt_fsname="virtfs", .mnt_dir="/NONROOT", .mnt_type="t1", .mnt_opts=""}, + {.mnt_fsname="virtfs2", .mnt_dir="/NONROOT", .mnt_type="t2", .mnt_opts=""}, + {.mnt_fsname="netns", .mnt_dir="net:[1234567]", .mnt_opts=""}, + {.mnt_fsname="rem:ote1",.mnt_dir="/REMOTE", .mnt_opts=""}, + {.mnt_fsname="rem:ote1",.mnt_dir="/REMOTE", .mnt_opts=""}, + {.mnt_fsname="rem:ote2",.mnt_dir="/REMOTE", .mnt_opts=""}, + }; + + if (done == 1) + { + nonroot_fs = getenv ("CU_NONROOT_FS"); + if (!nonroot_fs || !*nonroot_fs) + nonroot_fs = "/"; /* merge into / entries. */ + + remote_fs = getenv ("CU_REMOTE_FS"); + } + + if (done == 1 && !getenv ("CU_TEST_DUPE_INVALID")) + done++; /* skip the first entry. */ + + while (done++ <= 10) + { + if (!mntents[done-2].mnt_type) + mntents[done-2].mnt_type = "-"; + if (!mntents[done-2].mnt_opts) + mntents[done-2].mnt_opts = "-"; + if (STREQ (mntents[done-2].mnt_dir, "/NONROOT")) + mntents[done-2].mnt_dir = nonroot_fs; + if (STREQ (mntents[done-2].mnt_dir, "/REMOTE")) + { + if (!remote_fs || !*remote_fs) + continue; + else + mntents[done-2].mnt_dir = remote_fs; + } + return &mntents[done-2]; + } + + return NULL; +} +EOF + +# Then compile/link it: +gcc_shared_ k.c k.so \ + || framework_failure_ 'failed to build shared library' + +# Test if LD_PRELOAD works: +LD_PRELOAD=$LD_PRELOAD:./k.so df +test -f x || skip_ "internal test failure: maybe LD_PRELOAD doesn't work?" + +# The fake mtab file should only contain entries +# having the same device number; thus the output should +# consist of a header and unique entries. +LD_PRELOAD=$LD_PRELOAD:./k.so df -T >out || fail=1 +test $(wc -l <out) -eq $(expr 1 + $unique_entries) || { fail=1; cat out; } + +# With --total we should suppress the duplicate but separate remote file system +LD_PRELOAD=$LD_PRELOAD:./k.so df --total >out || fail=1 +test "$CU_REMOTE_FS" && elide_remote=1 || elide_remote=0 +test $(wc -l <out) -eq $(expr 2 + $unique_entries - $elide_remote) || + { fail=1; cat out; } + +# Ensure we don't fail when unable to stat (currently) unavailable entries +LD_PRELOAD=$LD_PRELOAD:./k.so CU_TEST_DUPE_INVALID=1 df -T >out || fail=1 +test $(wc -l <out) -eq $(expr 1 + $unique_entries) || { fail=1; cat out; } + +# df should also prefer "/fsname" over "fsname" +if test "$unique_entries" = 2; then + test $(grep -c '/fsname' <out) -eq 1 || { fail=1; cat out; } + # ... and "/fsname" with '/' as Mounted on over '/.' + test $(grep -cF '/.' <out) -eq 0 || { fail=1; cat out; } +fi + +# df should use the last seen devname (mnt_fsname) and devtype (mnt_type) +test $(grep -c 'virtfs2.*t2' <out) -eq 1 || { fail=1; cat out; } + +# Ensure that filtering duplicates does not affect -a processing. +LD_PRELOAD=$LD_PRELOAD:./k.so df -a >out || fail=1 +total_fs=6; test "$CU_REMOTE_FS" && total_fs=$(expr $total_fs + 3) +test $(wc -l <out) -eq $total_fs || { fail=1; cat out; } +# Ensure placeholder "-" values used for the eclipsed "virtfs" +test $(grep -c 'virtfs *-' <out) -eq 1 || { fail=1; cat out; } + +# Ensure that filtering duplicates does not affect +# argument processing (now without the fake getmntent()). +df '.' '.' >out || fail=1 +test $(wc -l <out) -eq 3 || { fail=1; cat out; } + +Exit $fail diff --git a/tests/df/skip-rootfs.sh b/tests/df/skip-rootfs.sh new file mode 100755 index 0000000..7b0855f --- /dev/null +++ b/tests/df/skip-rootfs.sh @@ -0,0 +1,53 @@ +#!/bin/sh +# Test df's behavior for skipping the pseudo "rootfs" file system. + +# Copyright (C) 2012-2020 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src +print_ver_ df + +# Protect against inaccessible remote mounts etc. +timeout 10 df || skip_ "df fails" + +# Verify that rootfs is in mtab (and shown when the -a option is specified). +# Note this is the case when /proc/self/mountinfo is parsed +# rather than /proc/mounts. I.e., when libmount is being used. +df -a >out || fail=1 +grep '^rootfs' out || skip_ 'no rootfs in mtab' + +# Ensure that rootfs is suppressed when no options is specified. +df >out || fail=1 +grep '^rootfs' out && { fail=1; cat out; } + +# Ensure that rootfs is yet skipped when explicitly specifying "-t rootfs". +# As df emits "no file systems processed" in this case, it would be a failure +# if df exited with status Zero. +returns_ 1 df -t rootfs >out || fail=1 +grep '^rootfs' out && { fail=1; cat out; } + +# Ensure that the rootfs is shown when explicitly both specifying "-t rootfs" +# and the -a option. +df -t rootfs -a >out || fail=1 +grep '^rootfs' out || { fail=1; cat out; } + +# Ensure that the rootfs is omitted in all_fs mode when it is explicitly +# black-listed. +df -a -x rootfs >out || fail=1 +grep '^rootfs' out && { fail=1; cat out; } + +test "$fail" = 1 && dump_mount_list_ + +Exit $fail diff --git a/tests/df/total-unprocessed.sh b/tests/df/total-unprocessed.sh new file mode 100755 index 0000000..e0c6e5b --- /dev/null +++ b/tests/df/total-unprocessed.sh @@ -0,0 +1,44 @@ +#!/bin/sh +# Ensure that df exits non-Zero and writes an error message when +# --total is used but no file system has been processed. + +# Copyright (C) 2012-2020 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src +print_ver_ df +require_mount_list_ + +cat <<\EOF > exp || framework_failure_ +df: no file systems processed +EOF + +# Check we exit with non-Zero. +# Note we don't check when the file system can't be determined +# as -t filtering is not applied in that case. +if test "$(df --output=fstype . | tail -n1)" != '-'; then + df -t _non_existent_fstype_ --total . 2>out && fail=1 + compare exp out || fail=1 +fi + +cat <<\EOF > exp || framework_failure_ +df: _does_not_exist_: No such file or directory +EOF + +# Ensure that df writes the error message also in the following case. +df --total _does_not_exist_ 2>out && fail=1 +compare exp out || fail=1 + +Exit $fail diff --git a/tests/df/total-verify.sh b/tests/df/total-verify.sh new file mode 100755 index 0000000..5538e23 --- /dev/null +++ b/tests/df/total-verify.sh @@ -0,0 +1,67 @@ +#!/bin/sh +# Ensure "df --total" computes accurate totals + +# Copyright (C) 2008-2020 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src +print_ver_ df +require_perl_ + +# Protect against inaccessible remote mounts etc. +timeout 10 df || skip_ "df fails" + +cat <<\EOF > check-df || framework_failure_ +my ($total, $used, $avail) = (0, 0, 0); +while (<>) + { + $. == 1 + and next; # skip first (header) line + # Recognize df output lines like these: + # /dev/sdc1 0 0 0 - /c + # tmpfs 1536000 12965 1523035 1% /tmp + # total 5285932 787409 4498523 15% - + /^(.*?) +(-?\d+|-) +(-?\d+|-) +(-?\d+|-) +(?:-|[0-9]+%) (.*)$/ + or die "$0: invalid input line\n: $_"; + if ($1 eq 'total' && $5 eq '-') + { + $total == $2 or die "$total != $2"; + $used == $3 or die "$used != $3"; + $avail == $4 or die "$avail != $4"; + my $line = <>; + defined $line + and die "$0: extra line(s) after totals\n"; + exit 0; + } + $total += $2 unless $2 eq '-'; + $used += $3 unless $3 eq '-'; + $avail += $4 unless $4 eq '-'; + } +die "$0: missing line of totals\n"; +EOF + +# Use --block-size=512 to keep df from printing rounded-to-kilobyte +# numbers which wouldn't necessarily add up to the displayed total. +df --total -P --block-size=512 > space || framework_failure_ +cat space # this helps when debugging any test failure +df --total -i -P > inode || framework_failure_ +cat inode + +$PERL check-df space || fail=1 +$PERL check-df inode || fail=1 + +test "$fail" = 1 && dump_mount_list_ + +Exit $fail diff --git a/tests/df/unreadable.sh b/tests/df/unreadable.sh new file mode 100755 index 0000000..109447e --- /dev/null +++ b/tests/df/unreadable.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# ensure that df can handle an unreadable argument + +# Copyright (C) 2009-2020 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src +print_ver_ df +skip_if_root_ + +touch unreadable || fail=1 +chmod a-r unreadable || fail=1 +df unreadable || fail=1 + +mkfifo_or_skip_ fifo +timeout 10 df fifo || fail=1 + +test "$fail" = 1 && dump_mount_list_ + +Exit $fail |