Also, check the block count.

* tests/find/ls-format-file.sh: where possible, set the test file up
such that its group owner is a group whose name is not the same as the
username of the current process.  Check the block count also.
---
 tests/find/ls-format-file.sh | 104 ++++++++++++++++++++++++++++-------
 1 file changed, 84 insertions(+), 20 deletions(-)

diff --git a/tests/find/ls-format-file.sh b/tests/find/ls-format-file.sh
index 9a9989d0..ec9f2331 100755
--- a/tests/find/ls-format-file.sh
+++ b/tests/find/ls-format-file.sh
@@ -28,11 +28,28 @@ LC_ALL=C
 export LC_ALL
 unset LANG
 
-# Create a test file with some known properties.
+user_owner="$( id -u -n )"
+if [ -z "${user_owner}" ]
+then
+    # This could mean that there is no entry in the password database.
+    skip_ "unable to determine username of the current user"
+fi
+
+# Create a test file with some known properties.  Because of
+# differences we cannot set a specific expectation for the number of
+# blocks occupied by a file, but we should be able to expect it to be
+# consistent with "ls -s".
 umask 077
+# If you change the value of testfile here to include any characters
+# special in either glob patterns or regular expressions, you will
+# need to re-check the tests in this file to ensure that they still do
+# what you want.
 testfile='lsme'
 filesize=765
 rm -f -- "${testfile}"
+# We get the data for the body from "yes" rather than /dev/zero just in case
+# the file system has some kind of optimization for files containing only
+# zero bytes (e.g. converting it to a hole).
 if ! ( yes non-empty | dd bs=1 count="${filesize}" of="${testfile}" ) 
2>/dev/null
 then
     framework_failure_ "failed to create test file ${testfile}"
@@ -46,27 +63,62 @@ then
     framework_failure_ "failed to set mtime of ${testfile}"
 fi
 
-# Check the actual properties of the file (to verify that the setup
-# was successful).
-check_prop() {
-    printf_fmt="${1}"
-    expected="${2}"
-    got="$( find "${testfile}" -printf "${printf_fmt}" )"
-
-    if [ "${expected}" != "${got}" ]
+# The script may be running with an effective group id which has the
+# same name as the user's username.  This is inconvenient as we would
+# not detect cases where the user and group name are swapped, either
+# by find or by this test, or where the test checks against the wrong
+# value (as in 9d50e9964449fb5e9f3da84a7c19c29dbf001bb5).
+#
+# So, find a group of which the current user is a member and which, if
+# possible is not the same as the user's username.
+choose_distinct_group() {
+    chosen=N
+    unset group_name
+    for group_name in $(groups)
+    do
+        if [ "${group_name}" != "${user_owner}" ]
+        then
+            printf '%s\n' "${group_name}"
+            chosen=Y
+            break
+        fi
+    done
+    if [ "${chosen}" = N ]
     then
-       framework_failure_ "expected test file ${testfile} to have -printf 
'${printf_fmt}\n' result '${expected}' but we got '${got}'"
+        # The user's only group is the same as their username.
+        # Default to the last (and only unless two groups have the
+        # same name) group name in the output of groups.
+        echo "${group_name:-}"
     fi
 }
+group_owner="$(choose_distinct_group)"
+if [ -z "${group_owner}" ]
+then
+    # This is very unusual, because even if /etc/group has been
+    # deleted, id should have printed the numeric value of the user's
+    # primary group.  However, there are situations in which this
+    # could happen.  For example, getgid() can fail on GNU Hurd.
+    skip_ "unable to find a group of which the current user is a member"
+fi
 
-check_prop '%M' "-rw-------"  # file mode
-check_prop '%n' 1            # link count
-check_prop '%s' "${filesize}" # size in bytes
-check_prop '%TF' "1992-03-14" # modification date
-check_prop '%TH:%TM' "19:00"  # modification time (without seconds)
+if ! chgrp "${group_owner}" "${testfile}"
+then
+    # There are some circumstances in which we cannot use a group in
+    # the filesystem even though getgroups(2) returns it.  An example
+    # is NFS version 2, on which the protocol limits the total number
+    # of group IDs that a process can use.  If I recall correctly the
+    # limit is 16.  Anyway, in this situation we will not claim that
+    # the test framework failed, because it is generally not going to
+    # be useful for the findutils maintainers to investigate these
+    # cases.  We also will not continue with a fallback value as these
+    # situations would be difficult to reproduce in the event of a bug
+    # report.
+    skip_ "failed to change group of ${testfile} to ${group_owner}"
+fi
 
 # Remember the file's inode number and block count.
-inum="$( find "${testfile}" -printf '%i\n')"
+inum="$( find "${testfile}" -printf '%i\n' )"
+blocks_expected="$( ls -s "${testfile}" | sed -e "s/${testfile}//g" )"
 # The system's value of BLOCKSIZE is implementation-dependent
 # ("ls -k" forces ls to use 1KiB blocks, but -ls is intended
 # to look like the output of ls -dils, without -k)
@@ -89,7 +141,13 @@ then
     fail_ "find -ls output does not end in newline"
 fi
 
-grep -e ' lsme$' < output.txt >/dev/null || fail_ "find -ls output should end 
with the file name"
+###############################################################################
+# Checks on the output fields generated by -ls, ignoring differences in the
+# number of spaces between fields.  If these tests break, this likely indicates
+# a bug in find.
+###############################################################################
+
+grep -e " ${testfile}"'$' < output.txt >/dev/null || fail_ "find -ls output 
should end with the file name"
 
 # The output is supposed to look like this:
 
@@ -108,9 +166,10 @@ awk < output.txt  \
     -v ME="${ME_}" \
     -v filename_expected="${testfile}" \
     -v inodenum="${inum}" \
+    -v blocks_expected="${blocks_expected}" \
     -v filesize="${filesize}" \
     -v uowner="$(id -un)" \
-    -v gowner="$(id -gn)" '
+    -v gowner="${group_owner}" '
 BEGIN {
       rv=2
 }
@@ -146,8 +205,13 @@ NR == 1 {
     printf("%s: failed test: expected inode number %d, got %s\n", ME, 
inodenum, $1);
   }
 
-  # field 2: size in blocks is ignored as we probably cannot assume
-  # any particular value for BLOCKSIZE.
+  # field 2: size in blocks
+  if (st_blocks != blocks_expected) {
+    rv=1
+    printf("%s: failed test: expected block count %d got %d\n", ME, 
blocks_expected, st_blocks);
+  } else {
+    printf("%s: block count %d looks OK\n", ME, st_blocks);
+  }
 
   # field 3 is the symbolic mode; we allow a final +
   # in case there is somehow a non-default ACL on the file.
-- 
2.47.3


Reply via email to