summaryrefslogtreecommitdiffstats
path: root/tests/ts/lsfd
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ts/lsfd')
-rwxr-xr-xtests/ts/lsfd/column-kthread41
-rw-r--r--tests/ts/lsfd/lsfd-functions.bash53
-rwxr-xr-xtests/ts/lsfd/mkfds-directory87
-rwxr-xr-xtests/ts/lsfd/mkfds-pipe-no-fork73
-rwxr-xr-xtests/ts/lsfd/mkfds-ro-block-device75
-rwxr-xr-xtests/ts/lsfd/mkfds-ro-regular-file78
-rwxr-xr-xtests/ts/lsfd/mkfds-rw-character-device50
-rwxr-xr-xtests/ts/lsfd/mkfds-socketpair48
-rwxr-xr-xtests/ts/lsfd/mkfds-symlink45
-rwxr-xr-xtests/ts/lsfd/option-filter-broken-exp36
-rwxr-xr-xtests/ts/lsfd/option-pid80
-rwxr-xr-xtests/ts/lsfd/option-summary62
12 files changed, 728 insertions, 0 deletions
diff --git a/tests/ts/lsfd/column-kthread b/tests/ts/lsfd/column-kthread
new file mode 100755
index 0000000..9fd10bf
--- /dev/null
+++ b/tests/ts/lsfd/column-kthread
@@ -0,0 +1,41 @@
+#!/bin/bash
+#
+# Copyright (C) 2021 Masatake YAMATO <yamato@redhat.com>
+#
+# This file is part of util-linux.
+#
+# This file 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 2 of the License, or
+# (at your option) any later version.
+#
+# This file 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.
+#
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kthread column"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+ts_skip_nonroot
+
+ts_check_test_command "$TS_CMD_LSFD"
+ts_check_prog "ps"
+
+[ "$(ps --no-headers -o comm 1)" = 'systemd' ] || ts_skip "pid 1 is not systemd"
+[ "$(ps --no-headers -o comm 2)" = 'kthreadd' ] || ts_skip "pid 2 is not kthreadd"
+
+ts_cd "$TS_OUTDIR"
+
+{
+ "$TS_CMD_LSFD" -o COMMAND,PID,USER,MODE,TYPE,NAME,KTHREAD \
+ -Q '(PID < 3) and ((ASSOC == "cwd") or (ASSOC == "rtd"))'
+ echo $?
+} > $TS_OUTPUT 2>&1
+
+ts_finalize
+
+
diff --git a/tests/ts/lsfd/lsfd-functions.bash b/tests/ts/lsfd/lsfd-functions.bash
new file mode 100644
index 0000000..b57ba11
--- /dev/null
+++ b/tests/ts/lsfd/lsfd-functions.bash
@@ -0,0 +1,53 @@
+#!/bin/bash
+#
+# Copyright (C) 2021 Masatake YAMATO <yamato@redhat.com>
+#
+# This file is part of util-linux.
+#
+# This file 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 2 of the License, or
+# (at your option) any later version.
+#
+# This file 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.
+#
+
+function lsfd_wait_for_pausing {
+ ts_check_prog "sleep"
+
+ local PID=$1
+ until [[ $(ps --no-headers -ostat "${PID}") =~ S.* ]]; do
+ sleep 1
+ done
+}
+
+function lsfd_compare_dev {
+ local LSFD=$1
+ local FILE=$2
+ local EXPR=$3
+
+ ts_check_prog "grep"
+ ts_check_prog "expr"
+ ts_check_prog "stat"
+
+ local DEV=$("${LSFD}" --raw -n -o DEV -Q "${EXPR}")
+ echo 'DEV[RUN]:' $?
+ local MAJ=${DEV%:*}
+ local MIN=${DEV#*:}
+ local DEVNUM=$(( ( MAJ << 8 ) + MIN ))
+ local STAT_DEVNUM=$(stat -c "%d" "$FILE")
+ echo 'STAT[RUN]:' $?
+ if [ "${DEVNUM}" == "${STAT_DEVNUM}" ]; then
+ echo 'DEVNUM[STR]:' 0
+ else
+ echo 'DEVNUM[STR]:' 1
+ # Print more information for debugging
+ echo 'DEV:' "${DEV}"
+ echo 'MAJ:MIN' "${MAJ}:${MIN}"
+ echo 'DEVNUM:' "${DEVNUM}"
+ echo 'STAT_DEVNUM:' "${STAT_DEVNUM}"
+ fi
+}
diff --git a/tests/ts/lsfd/mkfds-directory b/tests/ts/lsfd/mkfds-directory
new file mode 100755
index 0000000..cae5f2a
--- /dev/null
+++ b/tests/ts/lsfd/mkfds-directory
@@ -0,0 +1,87 @@
+#!/bin/bash
+#
+# Copyright (C) 2021 Masatake YAMATO <yamato@redhat.com>
+#
+# This file is part of util-linux.
+#
+# This file 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 2 of the License, or
+# (at your option) any later version.
+#
+# This file 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.
+#
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="directory"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_CMD_LSFD"
+ts_check_test_command "$TS_HELPER_MKFDS"
+
+ts_check_prog "stat"
+ts_check_prog "id"
+ts_check_prog "sed"
+
+ts_cd "$TS_OUTDIR"
+
+PID=
+FD=3
+EXPR=
+
+{
+ coproc MKFDS { "$TS_HELPER_MKFDS" directory $FD; }
+ if read -u ${MKFDS[0]} PID; then
+ EXPR='(PID == '"${PID}"') and (FD == '"$FD"')'
+ ${TS_CMD_LSFD} -n -o ASSOC,MODE,TYPE,FLAGS,NAME -Q "${EXPR}" | {
+ #
+ # Normalize the output:
+ #
+ # See https://github.com/util-linux/util-linux/issues/1511#issuecomment-1029968595
+ # It seems that syscalls opening a directory on mips64 GNU/Linux take the
+ # O_LARGEFILE flag.
+ #
+ sed -e 's/largefile,\|,largefile//'
+ }
+ echo 'ASSOC,MODE,TYPE,FLAGS,NAME': $?
+
+ LSFD_PID=$(${TS_CMD_LSFD} --raw -n -o PID -Q "${EXPR}")
+ echo 'PID[RUN]:' $?
+ [ "${LSFD_PID}" == "${PID}" ]
+ echo 'PID[STR]:' $?
+
+ LSFD_INODE=$(${TS_CMD_LSFD} --raw -n -o INODE -Q "${EXPR}")
+ echo 'INODE[RUN]:' $?
+ [ "${LSFD_INODE}" == "$(stat -c %i /)" ]
+ echo 'INODE[STR]:' $?
+
+ LSFD_UID=$(${TS_CMD_LSFD} --raw -n -o UID -Q "${EXPR}")
+ echo 'UID[RUN]:' $?
+ [ "${LSFD_UID}" == $(id -u) ]
+ echo 'UID[STR]:' $?
+
+ LSFD_USER=$(${TS_CMD_LSFD} --raw -n -o USER -Q "${EXPR}")
+ echo 'USER[RUN]:' $?
+ [ "${LSFD_USER}" == $(id -u -n) ]
+ echo 'USER[STR]:' $?
+
+ LSFD_NLINK=$(${TS_CMD_LSFD} --raw -n -o NLINK -Q "${EXPR}")
+ echo 'NLINK[RUN]:' $?
+ if [ "${LSFD_NLINK}" == $(stat -c %h /) ]; then
+ echo 'NLINK[STR]:' 0
+ else
+ echo 'NLINK[STR]:' 1
+ echo 'LSFD_NLINK:' "${LSFD_NLINK}"
+ echo 'stat reports:' "$(stat -c %h /)"
+ fi
+
+ kill -CONT ${PID}
+ wait ${MKFDS_PID}
+ fi
+} > $TS_OUTPUT 2>&1
+
+ts_finalize
diff --git a/tests/ts/lsfd/mkfds-pipe-no-fork b/tests/ts/lsfd/mkfds-pipe-no-fork
new file mode 100755
index 0000000..171b3b8
--- /dev/null
+++ b/tests/ts/lsfd/mkfds-pipe-no-fork
@@ -0,0 +1,73 @@
+#!/bin/bash
+#
+# Copyright (C) 2021 Masatake YAMATO <yamato@redhat.com>
+#
+# This file is part of util-linux.
+#
+# This file 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 2 of the License, or
+# (at your option) any later version.
+#
+# This file 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.
+#
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="pipe, no fork"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_CMD_LSFD"
+ts_check_test_command "$TS_HELPER_MKFDS"
+
+ts_check_prog "stat"
+ts_check_prog "readlink"
+
+ts_cd "$TS_OUTDIR"
+
+pipe_name()
+{
+ readlink /proc/$1/fd/$2
+}
+
+pipe_inode()
+{
+ stat -L -c %i /proc/$1/fd/$2
+}
+
+PID=
+FD0=3
+FD1=4
+EXPR=
+
+{
+ coproc MKFDS { "$TS_HELPER_MKFDS" pipe-no-fork $FD0 $FD1 nonblock=-w; }
+ if read -u ${MKFDS[0]} PID; then
+ EXPR='(PID == '"${PID}"') and ((FD == '"$FD0"') or (FD =='"$FD1"'))'
+ ${TS_CMD_LSFD} -n -o ASSOC,MODE,TYPE,SOURCE,FLAGS -Q "${EXPR}"
+ echo 'ASSOC,MODE,TYPE,SOURCE,FLAGS': $?
+
+ LSFD_PIDS=$(${TS_CMD_LSFD} --raw -n -o PID -Q "${EXPR}")
+ echo 'PID[RUN]:' $?
+ [ "${LSFD_PIDS}" == "$(printf '%d\n%d' ${PID} ${PID})" ]
+ echo 'PID[STR]:' $?
+
+ LSFD_NAMES=$(${TS_CMD_LSFD} --raw -n -o NAME -Q "${EXPR}")
+ echo 'NAMES[RUN]:' $?
+ [ "${LSFD_NAMES}" == "$(printf '%s\n%s' $(pipe_name $PID $FD0) $(pipe_name $PID $FD1))" ]
+ echo 'NAMES[STR]:' $?
+
+ LSFD_INODES=$(${TS_CMD_LSFD} --raw -n -o INODE -Q "${EXPR}")
+ echo 'INODES[RUN]:' $?
+ [ "${LSFD_INODES}" == "$(printf '%d\n%d' $(pipe_inode $PID $FD0) $(pipe_inode $PID $FD1))" ]
+ echo 'INODES[STR]:' $?
+
+ kill -CONT ${PID}
+ wait ${MKFDS_PID}
+ fi
+} > $TS_OUTPUT 2>&1
+
+ts_finalize
diff --git a/tests/ts/lsfd/mkfds-ro-block-device b/tests/ts/lsfd/mkfds-ro-block-device
new file mode 100755
index 0000000..86c1ba8
--- /dev/null
+++ b/tests/ts/lsfd/mkfds-ro-block-device
@@ -0,0 +1,75 @@
+#!/bin/bash
+#
+# Copyright (C) 2021 Masatake YAMATO <yamato@redhat.com>
+#
+# This file is part of util-linux.
+#
+# This file 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 2 of the License, or
+# (at your option) any later version.
+#
+# This file 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.
+#
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="block device with O_RDONLY"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+ts_skip_nonroot
+
+. $TS_SELF/lsfd-functions.bash
+
+ts_check_test_command "$TS_CMD_LSFD"
+
+ts_check_test_command "$TS_HELPER_MKFDS"
+
+ts_cd "$TS_OUTDIR"
+
+ts_device_init
+LSFD_LOOP_BDEV=$TS_LODEV
+LSFD_LOOP_BDEV_BASENAME=${LSFD_LOOP_BDEV##*/}
+LSFD_LOOP_BDEV_NUM=${LSFD_LOOP_BDEV_BASENAME#loop}
+
+PID=
+FD=3
+EXPR=
+
+{
+ coproc MKFDS { "$TS_HELPER_MKFDS" ro-block-device $FD blkdev=${LSFD_LOOP_BDEV}; }
+ if read -u ${MKFDS[0]} PID; then
+ EXPR='(PID == '"${PID}"') and (FD == '"$FD"')'
+ ${TS_CMD_LSFD} -n -o ASSOC,MODE,TYPE,POS,BLKDRV,DEVTYPE -Q "${EXPR}"
+ echo 'ASSOC,MODE,TYPE,,POS,,BLKDRV,DEVTYPE': $?
+
+ LSFD_NAME=$(${TS_CMD_LSFD} --raw -n -o NAME -Q "${EXPR}")
+ echo 'NAME[RUN]:' $?
+ [ "${LSFD_NAME}" == "${LSFD_LOOP_BDEV}" ]
+ echo 'NAME[STR]:' $?
+
+ LSFD_SOURCE=$(${TS_CMD_LSFD} --raw -n -o SOURCE -Q "${EXPR}")
+ echo 'SOURCE[RUN]:' $?
+ [ "${LSFD_SOURCE}" == "${LSFD_LOOP_BDEV_BASENAME}" ]
+ echo 'SOURCE[STR]:' $?
+
+ LSFD_MAJ_MIN=$(${TS_CMD_LSFD} --raw -n -o MAJ:MIN -Q "${EXPR}")
+ echo 'MAJ_MIN[RUN]:' $?
+ [ "${LSFD_MAJ_MIN}" == 7:"${LSFD_LOOP_BDEV_NUM}" ]
+ echo 'MAJ_MIN[STR]:' $?
+
+ LSFD_RDEV=$(${TS_CMD_LSFD} --raw -n -o RDEV -Q "${EXPR}")
+ echo 'RDEV[RUN]:' $?
+ [ "${LSFD_RDEV}" == 7:"${LSFD_LOOP_BDEV_NUM}" ]
+ echo 'RDEV[STR]:' $?
+
+ lsfd_compare_dev "${TS_CMD_LSFD}" "${LSFD_LOOP_BDEV}" "${EXPR}"
+
+ kill -CONT ${PID}
+ wait ${MKFDS_PID}
+ fi
+} > $TS_OUTPUT 2>&1
+
+ts_finalize
diff --git a/tests/ts/lsfd/mkfds-ro-regular-file b/tests/ts/lsfd/mkfds-ro-regular-file
new file mode 100755
index 0000000..9441a4e
--- /dev/null
+++ b/tests/ts/lsfd/mkfds-ro-regular-file
@@ -0,0 +1,78 @@
+#!/bin/bash
+#
+# Copyright (C) 2021 Masatake YAMATO <yamato@redhat.com>
+#
+# This file is part of util-linux.
+#
+# This file 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 2 of the License, or
+# (at your option) any later version.
+#
+# This file 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.
+#
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="read-only regular file"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+
+. $TS_SELF/lsfd-functions.bash
+
+ts_check_test_command "$TS_CMD_LSFD"
+
+ts_check_test_command "$TS_HELPER_MKFDS"
+
+ts_check_prog "stat"
+ts_check_prog "id"
+
+ts_cd "$TS_OUTDIR"
+
+PID=
+FD=3
+EXPR=
+
+{
+ target=/etc/passwd
+ coproc MKFDS { "$TS_HELPER_MKFDS" --comm ABC ro-regular-file $FD offset=1 file=$target; }
+ if read -u ${MKFDS[0]} PID; then
+ EXPR='(PID == '"${PID}"') and (FD == '"$FD"')'
+ ${TS_CMD_LSFD} -n -o COMMAND,ASSOC,MODE,TYPE,NAME,POS -Q "${EXPR}"
+ echo 'COMMAND,ASSOC,MODE,TYPE,NAME,POS': $?
+
+ LSFD_PID=$(${TS_CMD_LSFD} --raw -n -o PID -Q "${EXPR}")
+ echo 'PID[RUN]:' $?
+ [ "${LSFD_PID}" == "${PID}" ]
+ echo 'PID[STR]:' $?
+
+ LSFD_INODE=$(${TS_CMD_LSFD} --raw -n -o INODE -Q "${EXPR}")
+ echo 'INODE[RUN]:' $?
+ [ "${LSFD_INODE}" == "$(stat -c %i $target)" ]
+ echo 'INODE[STR]:' $?
+
+ LSFD_UID=$(${TS_CMD_LSFD} --raw -n -o UID -Q "${EXPR}")
+ echo 'UID[RUN]:' $?
+ [ "${LSFD_UID}" == $(id -u) ]
+ echo 'UID[STR]:' $?
+
+ LSFD_USER=$(${TS_CMD_LSFD} --raw -n -o USER -Q "${EXPR}")
+ echo 'USER[RUN]:' $?
+ [ "${LSFD_USER}" == $(id -u -n) ]
+ echo 'USER[STR]:' $?
+
+ LSFD_SIZE=$(${TS_CMD_LSFD} --raw -n -o SIZE -Q "${EXPR}")
+ echo 'SIZE[RUN]:' $?
+ [ "${LSFD_SIZE}" == $(stat -c %s $target) ]
+ echo 'SIZE[STR]:' $?
+
+ lsfd_compare_dev "${TS_CMD_LSFD}" $target "${EXPR}"
+
+ kill -CONT ${PID}
+ wait ${MKFDS_PID}
+ fi
+} > $TS_OUTPUT 2>&1
+
+ts_finalize
diff --git a/tests/ts/lsfd/mkfds-rw-character-device b/tests/ts/lsfd/mkfds-rw-character-device
new file mode 100755
index 0000000..4f368f6
--- /dev/null
+++ b/tests/ts/lsfd/mkfds-rw-character-device
@@ -0,0 +1,50 @@
+#!/bin/bash
+#
+# Copyright (C) 2021 Masatake YAMATO <yamato@redhat.com>
+#
+# This file is part of util-linux.
+#
+# This file 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 2 of the License, or
+# (at your option) any later version.
+#
+# This file 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.
+#
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="character device with O_RDWR"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+
+. $TS_SELF/lsfd-functions.bash
+
+ts_check_test_command "$TS_CMD_LSFD"
+
+ts_check_test_command "$TS_HELPER_MKFDS"
+
+ts_cd "$TS_OUTDIR"
+
+PID=
+FD=3
+EXPR=
+
+{
+ target=/dev/zero
+ coproc MKFDS { "$TS_HELPER_MKFDS" rw-character-device $FD chrdev=$target; }
+ if read -u ${MKFDS[0]} PID; then
+ EXPR='(PID == '"${PID}"') and (FD == '"$FD"')'
+ ${TS_CMD_LSFD} -n -o ASSOC,MODE,TYPE,NAME,SOURCE,POS,MAJ:MIN,CHRDRV,DEVTYPE,RDEV -Q "${EXPR}"
+ echo 'ASSOC,MODE,TYPE,NAME,SOURCE,POS,MAJ:MIN,CHRDRV,DEVTYPE,RDEV': $?
+
+ lsfd_compare_dev "${TS_CMD_LSFD}" $target "${EXPR}"
+
+ kill -CONT ${PID}
+ wait ${MKFDS_PID}
+ fi
+} > $TS_OUTPUT 2>&1
+
+ts_finalize
diff --git a/tests/ts/lsfd/mkfds-socketpair b/tests/ts/lsfd/mkfds-socketpair
new file mode 100755
index 0000000..7c0ef7d
--- /dev/null
+++ b/tests/ts/lsfd/mkfds-socketpair
@@ -0,0 +1,48 @@
+#!/bin/bash
+#
+# Copyright (C) 2021 Masatake YAMATO <yamato@redhat.com>
+#
+# This file is part of util-linux.
+#
+# This file 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 2 of the License, or
+# (at your option) any later version.
+#
+# This file 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.
+#
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="AF_UNIX socket pair created with socketpair(2)"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_CMD_LSFD"
+
+ts_check_test_command "$TS_HELPER_MKFDS"
+
+ts_check_prog "sed"
+
+ts_cd "$TS_OUTDIR"
+
+PID=
+FD0=3
+FD1=4
+EXPR=
+
+{
+ coproc MKFDS { "$TS_HELPER_MKFDS" socketpair $FD0 $FD1 socktype=DGRAM; }
+ if read -u ${MKFDS[0]} PID; then
+ EXPR='(PID == '"${PID}"') and ((FD == '"$FD0"') or (FD == '"$FD1"'))'
+ ${TS_CMD_LSFD} -n -o ASSOC,MODE,TYPE,SOURCE,PROTONAME -Q "${EXPR}" | sed -e 's/UNIX-DGRAM/UNIX/'
+ echo 'ASSOC,MODE,TYPE,SOURCE,PROTONAME': $?
+
+ kill -CONT ${PID}
+ wait ${MKFDS_PID}
+ fi
+} > $TS_OUTPUT 2>&1
+
+ts_finalize
diff --git a/tests/ts/lsfd/mkfds-symlink b/tests/ts/lsfd/mkfds-symlink
new file mode 100755
index 0000000..e4513d9
--- /dev/null
+++ b/tests/ts/lsfd/mkfds-symlink
@@ -0,0 +1,45 @@
+#!/bin/bash
+#
+# Copyright (C) 2021 Masatake YAMATO <yamato@redhat.com>
+#
+# This file is part of util-linux.
+#
+# This file 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 2 of the License, or
+# (at your option) any later version.
+#
+# This file 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.
+#
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="symbolic link itself opened with O_PATH"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_CMD_LSFD"
+
+ts_check_test_command "$TS_HELPER_MKFDS"
+
+ts_cd "$TS_OUTDIR"
+
+PID=
+FD=3
+EXPR=
+
+{
+ coproc MKFDS { "$TS_HELPER_MKFDS" symlink $FD path=/dev/stdin; }
+ if read -u ${MKFDS[0]} PID; then
+ EXPR='(PID == '"${PID}"') and (FD == '"$FD"')'
+ ${TS_CMD_LSFD} -n -o ASSOC,MODE,TYPE,NAME,FLAGS -Q "${EXPR}"
+ echo 'ASSOC,MODE,TYPE,NAME,FLAGS': $?
+
+ kill -CONT ${PID}
+ wait ${MKFDS_PID}
+ fi
+} > $TS_OUTPUT 2>&1
+
+ts_finalize
diff --git a/tests/ts/lsfd/option-filter-broken-exp b/tests/ts/lsfd/option-filter-broken-exp
new file mode 100755
index 0000000..58b48e1
--- /dev/null
+++ b/tests/ts/lsfd/option-filter-broken-exp
@@ -0,0 +1,36 @@
+#!/bin/bash
+#
+# Copyright (C) 2022 Masatake YAMATO <yamato@redhat.com>
+#
+# This file is part of util-linux.
+#
+# This file 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 2 of the License, or
+# (at your option) any later version.
+#
+# This file 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.
+#
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="passing broken expressions to -Q option"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_CMD_LSFD"
+
+ts_cd "$TS_OUTDIR"
+
+{
+ $TS_CMD_LSFD -Q ''
+ $TS_CMD_LSFD -Q '('
+ $TS_CMD_LSFD -Q ')'
+ $TS_CMD_LSFD -Q '(FD == 1)garbage'
+ $TS_CMD_LSFD -Q 'FD'
+ $TS_CMD_LSFD -Q 'NOSUCHCOLUMN'
+} > $TS_OUTPUT 2>&1
+
+ts_finalize
diff --git a/tests/ts/lsfd/option-pid b/tests/ts/lsfd/option-pid
new file mode 100755
index 0000000..65365bf
--- /dev/null
+++ b/tests/ts/lsfd/option-pid
@@ -0,0 +1,80 @@
+#!/bin/bash
+#
+# Copyright (C) 2021 Masatake YAMATO <yamato@redhat.com>
+#
+# This file is part of util-linux.
+#
+# This file 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 2 of the License, or
+# (at your option) any later version.
+#
+# This file 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.
+#
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="--pid option"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+ts_skip_nonroot
+
+ts_check_test_command "$TS_CMD_LSFD"
+ts_check_test_command "$TS_HELPER_MKFDS"
+ts_check_prog "ps"
+
+ts_cd "$TS_OUTDIR"
+
+[ "$(ps --no-headers -o comm 1)" = 'systemd' ] || ts_skip "pid 1 is not systemd"
+
+PID=
+FD=3
+EXPR=
+QOUT=
+POUT=
+
+{
+ coproc MKFDS { "$TS_HELPER_MKFDS" ro-regular-file $FD file=/etc/group; }
+ if read -u ${MKFDS[0]} PID; then
+ EXPR='((PID == '"${PID}"') or (PID == 1)) and (FD == '"$FD"')'
+ QOUT=$(${TS_CMD_LSFD} -n -o ASSOC,MODE,TYPE,FLAGS,NAME -Q "${EXPR}")
+ echo "QOUT:" $?
+
+ POUT=$(${TS_CMD_LSFD} --pid="1 $PID" -n -o ASSOC,MODE,TYPE,FLAGS,NAME -Q "(FD == $FD)")
+ echo "POUT[--pid=1 PID]:" $?
+ [ "${QOUT}" = "${POUT}" ]
+ echo "EQ[--pid=1 PID]:" $?
+
+ POUT=$(${TS_CMD_LSFD} --pid="$PID 1" -n -o ASSOC,MODE,TYPE,FLAGS,NAME -Q "(FD == $FD)")
+ echo "POUT[--pid=PID 1]:" $?
+ [ "${QOUT}" = "${POUT}" ]
+ echo "EQ[--pid=PID 1]:" $?
+
+ POUT=$(${TS_CMD_LSFD} --pid="1,$PID" -n -o ASSOC,MODE,TYPE,FLAGS,NAME -Q "(FD == $FD)")
+ echo "POUT[--pid=1,PID]:" $?
+ [ "${QOUT}" = "${POUT}" ]
+ echo "EQ[--pid=1,PID]:" $?
+
+ POUT=$(${TS_CMD_LSFD} --pid="$PID,1" -n -o ASSOC,MODE,TYPE,FLAGS,NAME -Q "(FD == $FD)")
+ echo "POUT[--pid=PID,1]:" $?
+ [ "${QOUT}" = "${POUT}" ]
+ echo "EQ[--pid=PID,1]:" $?
+
+ POUT=$(${TS_CMD_LSFD} -p 1 --pid="$PID" -n -o ASSOC,MODE,TYPE,FLAGS,NAME -Q "(FD == $FD)")
+ echo "POUT[-p 1 --pid=PID]:" $?
+ [ "${QOUT}" = "${POUT}" ]
+ echo "EQ[-p 1 --pid=PID]:" $?
+
+ POUT=$(${TS_CMD_LSFD} -p "$PID" --pid=1 -n -o ASSOC,MODE,TYPE,FLAGS,NAME -Q "(FD == $FD)")
+ echo "POUT[-p PID --pid=1]:" $?
+ [ "${QOUT}" = "${POUT}" ]
+ echo "EQ[-p PID --pid=1]:" $?
+
+ kill -CONT ${PID}
+ wait ${MKFDS_PID}
+ fi
+} > $TS_OUTPUT 2>&1
+
+ts_finalize
diff --git a/tests/ts/lsfd/option-summary b/tests/ts/lsfd/option-summary
new file mode 100755
index 0000000..e27122a
--- /dev/null
+++ b/tests/ts/lsfd/option-summary
@@ -0,0 +1,62 @@
+#!/bin/bash
+#
+# Copyright (C) 2021 Masatake YAMATO <yamato@redhat.com>
+#
+# This file is part of util-linux.
+#
+# This file 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 2 of the License, or
+# (at your option) any later version.
+#
+# This file 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.
+#
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="--summary option"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+
+. $TS_SELF/lsfd-functions.bash
+
+ts_check_test_command "$TS_CMD_LSFD"
+ts_check_test_command "$TS_HELPER_MKFDS"
+ts_check_prog "ps"
+
+ts_cd "$TS_OUTDIR"
+
+FD=3
+F_GROUP=/etc/group
+F_PASSWD=/etc/passwd
+PIDS=
+PID=
+
+for i in {1..10}; do
+ "$TS_HELPER_MKFDS" -q ro-regular-file $FD file=$F_GROUP &
+ PID=$!
+ PIDS="${PIDS} ${PID} "
+ lsfd_wait_for_pausing "${PID}"
+done
+
+for i in {1..3}; do
+ "$TS_HELPER_MKFDS" -q ro-regular-file $FD file=$F_PASSWD &
+ PID=$!
+ PIDS="${PIDS} ${PID} "
+ lsfd_wait_for_pausing "${PID}"
+done
+
+${TS_CMD_LSFD} -n --summary=only \
+ --pid="${PIDS}" \
+ --counter=GROUP:'(NAME == "/etc/group")' \
+ --counter=PASSWD:'(NAME == "/etc/passwd")' \
+ --counter=PROC:'(ASSOC == "exe")' \
+ > $TS_OUTPUT 2>&1
+
+for PID in ${PIDS}; do
+ kill -CONT "${PID}"
+done
+
+ts_finalize