1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
|
#!/bin/sh
# Unit Tests for GNU Datamash - I/O error simulation
# Copyright (C) 2014-2021 Assaf Gordon <assafgordon@gmail.com>
#
# This file is part of GNU Datamash.
#
# GNU Datamash 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.
#
# GNU Datamash 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 GNU Datamash. If not, see <https://www.gnu.org/licenses/>.
#
# Written by Assaf Gordon
##
## This script tests datamash's handling of I/O errors.
## It requires special setup, and is skipped unless found.
##
. "${test_dir=.}/init.sh"; path_prepend_ ./src
expensive_
fail=0
##
## The required mounted file-systems
##
FULLFS=/tmp/fullfs/
BADFS=/tmp/badfs/
which mountpoint >/dev/null 2>&1 ||
skip_ "requires mountpoint program"
stdbuf --version >/dev/null 2>&1 ||
skip_ "requires GNU stdbuf program"
stat --version >/dev/null 2>&1 ||
skip_ "requires GNU stat program"
mountpoint -q "$FULLFS" ||
skip_ "requires special mounted file system '$FULLFS'"
mountpoint -q "$BADFS" ||
skip_ "requires special mounted file system '$BADFS'"
##
## Clean files in the (almost) full file-system.
## This will ensure few writes are successful before getting "no space" error
## (unlike "/dev/full").
##
clean_full_fs()
{
find "$FULLFS" -maxdepth 1 -type f -delete ||
framework_failure_ "failed to clean full-fs"
# Give the system time to actually delete the files
fullfs_retries=1
FREE=0
while test $fullfs_retries -lt 5 && test $FREE -le 5 ; do
sync ; sleep 1
FREE=$(stat --file-system -c %a "$FULLFS") ||
framework_failure_ "failed to find free space on $FULLFS"
fullfs_retries=$((fullfs_retries+1))
done
# Ensure the (almost) full file system has a bit of free space...
test "$FREE" -gt 5 ||
framework_failure_ "almost-full-file system has no free space"
# ... but not too much (otherwise the program will not get "no space" errors).
test "$FREE" -lt 64 ||
framework_failure_ "almost-full-file system has too much free spcae"
}
##
## Sanity checks:
## 1. Ensure the corrupted file system is corrupted
cat "$BADFS/numbers.txt" >/dev/null 2>&1 &&
framework_failure_ "corrupted file system did not trigger I/O error"
## 2. Ensure the (almost) full file system gets full
clean_full_fs
seq 10000 >"$FULLFS/test.txt" 2>/dev/null &&
framework_failure_ "almost full file system did not trigger no-space error"
clean_full_fs
## Test 1:
## input error, reading file directly
datamash sum 1 < "$BADFS/numbers.txt" >/dev/null &&
{ warn_ "datamash failed to detect read error" ; fail=1 ; }
## Test 2:
## input error, using sort (and popen/pipe)
datamash -s -g 1 sum 1 < "$BADFS/numbers.txt" >/dev/null &&
{ warn_ "datamash+sort failed to detect read error" ; fail=1 ; }
## Test 3:
## output error, default line-buffering
seq 10000 | datamash -g 1 count 1 > "$FULLFS/test.txt" &&
{ warn_ "datamash failed to detect no-space error" ; fail=1 ; }
clean_full_fs
## Test 4:
## output error, with line-buffering.
## This means few of the first "write()" calls will succeed,
## and later ones should fail with "no space" (which is different than
## writing to "/dev/full").
seq 10000 | stdbuf -oL datamash -g 1 count 1 > "$FULLFS/test.txt" &&
{ warn_ "datamash failed to detect no-space error" ; fail=1 ; }
clean_full_fs
Exit $fail
|