
			The Lsof Test Suite

			    Contents

		A.  Introduction
		    1.  Test Suite Goals
		    2.  Not a FAQ
		    3.  Where have the tests been tested?
		B.  Test Methodology
		    1.  Test Limitations
		    2.  Test Data Base and Scripts
		    3.  The Makefile
		    4.  The Lsof Executable and LT_LSOF_PATH
		    5.  Automated Testing
		C.  Configure Script Participation
		    1.  config.cc
		    2.  config.cflags
			2.1  config.cflags Contents
		    3.  config.ldflags
		    4.  config.xobj
		D.  Cleaning -- Quick or Spotless
		E.  Test Libraries
		    1.  LTlib.c
		F.  The Individual Tests
		    1.  LTbasic, a Basic Lsof Test
		    2.  LTbigf, Test Sizes and Offsets for Large
			(> 32 bit) Files
		    3.  LTdnlc, Test the Kernel's Dynamic Name Lookup
		        Cache
		    4.  LTlock, Lock Tests
		    5.  LTnfs, NFS Test
		    6.  LTnlink, Link Count Test
		    7.  LTsock, Test IPv4 Sockets
		    8.  LTszoff, Test Sizes and Offsets for Small
			(< 32 bit) Files
		    9.  LTunix, Test UNIX Domain Sockets
		Appendix A, Test Files
		Appendix B, Test Validations
		Appendix C, Test Failures


A. Introduction
===============

Lsof has an automated test suite whose components are located in
the tests/ sub-directory of the lsof top-level directory.  Configuring,
building and testing lsof can be done with these shell commands:

    $ Configure -n <dialect-abbreviation>
    $ make
    $ cd tests
    $ make

That's all there is to it!

But read on for more dirty details.

A.1. Test Suite Goals
=====================

The lsof test suite attempts to test basic lsof features.  It does
not promise to test every lsof feature for every supported dialect.
(That's a nearly impossible goal.)

A.2. Not a FAQ
==============

One caution: this is not a frequently asked questions (FAQ) file
for the lsof test suite.  FAQs on the lsof test suite will be found
in the one and only lsof FAQ in file 00FAQ of the lsof distribution,
or on-line at:

    ftp://vic.cc.purdue.edu/pub/tools/unix/lsof/FAQ

A.3. Where have the tests been tested?
======================================

OK, I just said this isn't an FAQ and here comes a question and
answer that looks like an FAQ.  Consider it a Very FAQ and indulge
me -- let me answer it here.

The lsof test suite hasn't been tested everywhere it might be
possible to build lsof successfully.  That "everywhere" includes
dialect versions -- e.g., Solaris < 2.6 -- to which I no longer
have access.  On some dialect versions to which I have access, some
tests won't run because the test system lacks support.

In "Appendix B, Test Validations" I've tried to list where I compiled
and tested the test suite and information on any tests I was unable
to run.  In "Appendix C, Test Failures" I list where the test suite
fails and why it failed.

A.4 Where are the tests?
========================

Another FAQ whose answer is that the tests are in the tests/
sub-directory of the main lsof source directory.


B. Test Methodology
===================

The test suite is made up of individual C programs.  Test setup is
performed by the lsof Configure script itself, which writes a set
of dialect configuration files in the tests/ subdirectory.  (See
"C. Configure Script Participation.")

Each program or script performs a specialized tests.  Those tests
are described below in "F. The Individual Tests".

Each test measures lsof functionality by putting a specific lsof
command execution at the end of an in-bound (to the test) pipe.
The caller asks lsof to write its results to the pipe in field
output form.  (See the -F option in the lsof man page.)  That has
a limitation, described below in "B.1 Test Limitations."

Using an in-bound lsof pipe allows the tests to measure a great
deal of lsof functionality, including as an interesting side effect,
the performance of field output.  Consequently, there's no special
field output test.

B.1. Test Limitations
=====================

One limitation of the tests is that they don't measure lsof formatted
output -- i.e., the output normally see when lsof is run.  There
are just too many variants of lsof output produced across the range
of dialects where lsof runs, so field output is a more constant
way to process lsof output.

But using field output does mean that the test suite doesn't check
for lsof formatting problems, except in the field output itself.


B.2. Test Data Base and Scripts
===============================

The tests/TestDB file contains a simple data base that describes
where the tests have been validated.  Entries are formed from a
combination of the lines in the tests/config.cflags file produced
by the lsof Configure script.  The entries can be considered "lsof
dialect footprints."

Two shell scripts support TestDB.  The first Add2TestDB will add
an lsof dialect footprint to tests/TestDB.  I don't recommend you
use this script.  Mostly it's for my use when I find that the test
suite has been validated on a new dialect.

The CkTestDB script is used by the Makefile to compare an lsof
dialect footprint to tests/TestDB.  If one isn't located, the script
issues a warning and asks if running the test suite should continue.

B.3. The Makefile
=================

The Makefile in tests/ runs the tests in the test suite.  It has
these useful rules.

    all		runs the basic test and the standard tests.

    auto        runs the basic test and the standard tests as
		silently as possible.  This rule is designed for
		lsof build scripts that want a quick noiseless test
		of what they built.  This rule inhibits any CkTestDB
		go-ahead request (See below.) by making sure its
		standard input file isn't a TTY.

    clean       removes test and compiler output.  (See the "Cleaning
		-- Quick or Spotless" section.)

    opt		runs the optional tests.
    optional

    spotless    does what the clean rule does and also removes the
		config.* files created by ../Configure.  (See the
		"Cleaning -- Quick or Spotless" section.)

    std		runs the basic test and the standard tests.
    standard

Rules in the Makefile that run tests first run the CkTestDB script.
It makes sure the tests have been validated on the UNIX dialect.  If
not, and if standard input is a TTY, CkTestDB asks for a go-ahead
signal.  If standard input isn't a TTY, CkTestDB aborts the test run.

The Makefile has some cleaning rules, further described in "Cleaning
-- Quick or Spotless."

B.4. The Lsof Executable and LT_LSOF_PATH
=========================================

Normally the programs in the test suite use the lsof executable in
their parent directory, ../lsof.  Usually that lsof has just been
built and testing it is the next logical step.

Be careful that ../lsof has sufficient permission to access the
necessary kernel resources -- e.g., /dev/kmem, /dev/mem, /proc,
etc.  If it doesn't the tests will fail.  (The tests do check to
see if they can open /dev/mem and /dev/kmem for read access if
LT_KMEM is defined in config.cflags and if the path to the lsof
executable is ../lsof.)

Here are two possible ways you can make sure the lsof being tested
has sufficient permission: 1) use chmod and chgrp to enable its
running and put its path in LT_LSOF_PATH, thus disabling the check
in the tests for kernel memory access; or 2) run the tests (and
hence the lsof being tested) under a login that has sufficient
permission -- e.g., is in a group that can read /dev/kmem.

You can direct the tests to use a different lsof executable by
specifying its path in the LT_LSOF_PATH environment variable.  To
test an lsof executable already installed in /usr/local/etc --
provided that lsof is at revision 4.63 or higher -- do this:

    $ LT_LSOF_PATH=/usr/local/etc/lsof
    $ export LT_LSOF_PATH
    $ cd .../lsof_<version>/tests
    $ make

When you specify an alternate executable path via LT_LSOF_PATH,
that also prevents the tests from checking to see if they have
kernel memory access.

B.5 Automated Testing
=====================

Normally the lsof test suite is wordy and may require interaction.
When you want to avoid those interferences, use the tests/Makefile
"auto" rule.  (See B.5 Automated Testing.)


C. Configure Script Participation
=================================

An important step in setting up the test suite is performed by the
Configure script in the lsof home directory (the parent to tests/.)

Configure writes four files in tests/ that describe how the tests
are to be compiled, configured and loaded.  The files also describe
options that Configure selected that are important to the test
suite.

C.1. config.cc
==============

This file, tests/config.cc, contains the name of or the path to
the C compiler used to compile lsof.  The Makefile in tests/ uses
this file in place of the standard make(1) CC string with a shell
in-place execution statement -- i.e., `cat config.cc`.

If the LSOF_CC environment variable is supplied to the lsof Configure
script, its value will appear in the tests/config.cc file.

C.2. config.cflags
==================

This file, tests/config.cflags, contains C compiler flags that
tests/Makefile uses to compile the C programs in the test suite.
As with the compiler file, tests/config.cc, the make rules incorporate
the contents of this file into C compiler options with `cat
config.cflags`.

This file is also used by the Add2TestDB and CkTestDB shells scripts
to build and match lsof dialect footprints.  (See "B.2. Test Data
Base and Scripts.")

C.2.1 config.cflags Contents
============================

The config.cflags file may contain the following C compiler flags.


    -DLT_AIXA               is present if lsof was built for AIX.
			    It contains the AIX architecture flag.
			    (See the lsof Configure script or
			    dialects/aix/dlsof.h for more information
			    on the AIX architecture flag.)

    -DLT_BIGF		    is present if lsof was built for a dialect
			    that has large file (sizes and offsets >
			    32 bits).

    -DLT_CC		    is present if the lsof compiler is cc.

    -DLT_DIAL_<abbr>	    always ends in (the <abbr> part) the
			    "canonical" -- i.e., usually the most
			    common abbreviation by which the dialect
			    is known.

			    Example: -DLT_DIAL_solaris

    -DLT_GCC		    is present if the lsof compiler is gcc.

    -DLT_K64		    is present if lsof has been built for a
			    64 bit kernel

    -DLT_KMEM		    is present if lsof has been built to
			    use /dev/kmem to obtain kernel values.

    -DLT_VERS=<vn>	    contains the version number for the
			    dialect, as used in lsof pre-processor
			    tests.

			    Example for Solaris 8: -DLT_VERS=80000

The config.cflags file may also contain dialect-specific compiler
flags needed to activate a specific feature on the dialect.  For
example, for HP-UX config.cflags might contain:

    -D_LARGEFILE64_SOURCE   This compiler flag enables the use of
			    large-file system library functions
			    --e.g., open64().

			    The lsof Configure script stanzas for
			    the dialects select these options.


C.3. config.ldflags
===================

This file, tests/config.ldflags, contains the dialect loader flags
-- i.e., the equivalent to make(1) LFLAGS -- for loading the test
programs.

Example for Solaris: -lsocket           this adds the socket library
					to the loading of the lsof
					test programs.

Example for UnixWare: -lsocket -lnsl    this adds the socket and
					name server libraries to
					the loading of the lsof
					test programs.


C.4. config.xobj
================

This file, tests/config.xobj, contains the paths to any extra object
files (.o's) that must be loaded when the test suite C programs
are loaded.  Like tests/config.cc and tests/config.cflags, it's
incorporated into the loader statements of the tests/Makefile's
make rules with `cat config.xobj`.

Examples for DEC OSF/1 and NEXTSTEP:

    ../lib/snpf.o       this loads the private lsof object file
			that contains an snprintf() function.  (The
			DEC OSF/1 4.0 and NEXTSTEP 3.1 C libraries
			don't have snprintf().)


D. Cleaning -- Quick or Spotless
================================

While on the subject of make rules, here's a description of the
two cleaning rules in tests/Makefile:

    clean       a "quick" clean that removes compiled object files,
		executables and test files.  It does NOT remove
		the configuration files that ../Configure and the
		config.perl rule wrote.

    spotless    cleans out everything clean does -- plus the
		configuration files that ../Configure and the
		config.perl rule wrote.

		This is the rule used when `./Configure -clean` is
		specified.  If this rule is used, `../Configure -n
		<abbr>` and `../make`) must be run again before
		the test suite can be used.


E. Test Library
===============

The lsof test suite provides a C library.

E.1. LTlib.c
============

This is a C library of common functions used by tests.  configured
at compile time by the contents of tests/config.cflags, it uses
the single header file tests/LsofTest.h.  LsofTest.h tailors its
definitions to the dialect at compile time, using the LT_DIAL_*
definitions in config.cflags.

Two particularly useful functions in the library are: ExecLsof(),
which will execute an lsof child process; and RdFromLsof(), which
will read from the in-bound lsof pipe, and decode the fields into
structures that are easy for C programs to process.

This library is a good model for processing field output in a C
program from an in-bound lsof pipe.

The source for the library, tests/LTlib.c, contains more documentation.


F. The Individual Tests
=======================

The individual tests are listed in this section.  The listings
explain what the tests do, a few errors they might report, and how
to use options and environment variables to customize the tests.

The test descriptions are listed in this section in alphabetical
order, not in the order they are run by tests/Makefile.

The Makefile runs the tests in three groups, basic tests, standard
tests, and optional tests.  The default make "all" rule runs the
basic and standard tests.  (The "standard", "std", and "test"
Makefile rules are synonyms to "all".)  If the standard tests
succeed, the Makefile suggests running the optional tests with the
"opt" (or "optional") rule.

    The basic test:
	LTbasic

    Standard tests:
	LTnlink
	LTsock
	LTszoff
	LTunix

    Optional tests:
	LTbigf
	LTdnlc
	LTlock
	LTnfs

The basic and standard tests should all succeed on all dialects,
although LTnlink may warn that it can't perform its unlink test on
an NFS file system.

The optional tests may run,  they may be disabled for specific
dialects, or they may fail because of special resource needs --
e.g., LTbigf will run only on UNIX dialects where it knows how to
handle files whose lengths exceed 32 bits, and LTnfs needs access
to an NFS file system mounted from a remote NFS server.

Tests that need special resources usually provide a hint about the
resources when they fail.  Information about special resource needs
may also be found in the following sections about the individual
tests.

G.1. LTbasic, a Basic Lsof Test
===============================

This is the basic lsof test.  If it doesn't run, it's not likely
any other tests will run, either.  Hence, if it fails, the tests/
Makefile runs no other tests.

This test uses lsof to locate files in the lsof process, including
current working directory, the lsof executable, and the /dev/kmem
open file.

Finding the lsof executable isn't possible on all dialects -- e.g.,
Apple Darwin -- so that test is disabled there.  It may not be
possible on AIX if lsof was compiled without support for its -X
option.

Finding /dev/kmem use by lsof is only possible on dialects where
lsof uses /dev/kmem.  The -DLT_KMEM define indicates that.

Run this test:

    $ ./LTbasic

Environment variables: LT_LSOF_PATH defines the path to the lsof
		       executable.  (The default is ../lsof.)

G.2. LTbigf, Test Sizes and Offsets for Large (> 32 bit) Files
==============================================================

This is a test in the optional test group.

This test is effective only when ../Configure has put -DLT_BIGF in
tests/config.cflags.  Without that definition this test simply
reports that the dialect doesn't support large files.  That report
is accompanied by a successful test exit code, so that the runner
of the test (e.g., the tests/Makefile) won't believe the test
failed.

When a dialect does support large files, the test attempts to create
a file that looks very large -- e.g., has a length as reported by
ls(1) of 0x140000000 bytes.  However, the file really has only a
small amount of data in it, the rest of the file consists of a
large standard UNIX file system "hole."

By default the test file is named tests/config.LTbigf<PID>, where
PID is the Process ID of the LTbigf process.

When that file is not on a file system enabled for large files, or
when the process that runs LTbigf can't create a big file, LTbigf
will report an error.  The error will be accompanied by hints that
the -p option may need to be used to define a path where the test
can write a large file, or the process ulimit file block size may
need to be raised -- e.g., to "unlimited."

LTbigf can't test file offset reporting on Linux, because its /proc
file system doesn't report them to lsof.

Run this test:

    $ ./LTbigf [-p <path>]

Environment variables: LT_LSOF_PATH defines the path to the lsof
		       executable.  (The default is ../lsof.)

G.3. LTdnlc, Test the Kernel's Dynamic Name Lookup Cache
========================================================

This is a test in the optional test group.

This test asks lsof to locate the current working directory of its
own process and report the path it has assembled from the components
it found in the kernel's Dynamic Name Lookup Cache (DNLC) or via
other dialect-specific methods.  (E.g., Linux, HP-UX 11.11, and
some Tru64 UNIX versions have private name lookup methods.)

The test checks what lsof reports as the current working directory
path with for any missing components and counts the number of full
paths returned.  (Symbolic link complications prevent testing for
exact path matches.)  The test is repeated.  If full paths are
returned at least half the time, the test considers itself successful.

This test can't be run on AIX, because lsof can't access the DNLC
there.  It can't be run on Darwin, either, because insufficient
DNLC information is available there.

Run this test:

    $ ./LTdnlc

Environment variables: LT_LSOF_PATH defines the path to the lsof
		       executable.  (The default is ../lsof.)

G.4. LTlock, Lock Tests
=======================

This is a test in the optional test group.

This test uses flock() and fcntl() to set and clear file locks,
and measures lsof's ability to report them.  The choice of system
lock call is based on the dialect.  (There are LT_DIAL_* pre-processor
tests in LTlock.c.)

This test can't be run on an NFS client file system, because NFS
lock information is kept on the server.  Lsof on the client can't
see that server kernel data.

By default the test attempts to create a file names
tests/config.LTlock<PID>, where PID is the Process ID of the locking
test process.  It uses lsof to determine if the file is on a client
NFS file system.  If it is, the test aborts, hinting that the -p
option can be used to specify a non-client-NFS test file path.

This test can't be run on Darwin, because insufficient file system
lock information is available to lsof there.

Run this test:

    $ ./LTlock [-p <path>]

Environment variables: LT_LSOF_PATH defines the path to the lsof
		       executable.  (The default is ../lsof.)

G.6. LTnfs, NFS Test
====================

This is a test in the optional test group.

This test verifies that lsof can locate files mounted on a client
NFS system from an NFS server.

By default it creates a test file, tests/config.LTnfs<PID>, where
PID is the Process ID of the test process.  The test then uses lsof
to find the file on an NFS file system.

If lsof can't find the file the test warns that the test file might
not be on an NFS file system and hints that the -p option may be
used to specify the path of an NFS file, provided the test can have
read access to it there.  The test warning also states that the
file at the path specified with -p must be a regular file, not a
directory.

This test can't be run on Darwin, because insufficient NFS file
information is available to lsof there.

Run this test:

    $ ./LTnfs [-p <path>]

Environment variables: LT_LSOF_PATH defines the path to the lsof
		       executable.  (The default is ../lsof.)

G.7. LTnlink, Link Count Test
=============================

This is a test in the standard test group.

The test checks lsof's reporting of link count (nlink in UNIX
argot.)

It creates a test file in the current working directory name
tests/config.LTnlink<PID>, where  PID is the Process ID of the test
process.  It then uses stat(2) and lsof to measure the link count
of the file.

If nlink creates the test file in the current working directory
and it is on an NFS file system, nlink won't be able to perform
one section of its test.  In that section the test file is unlinked
so its link count will be zero and lsof is asked to find it among
the set of files whose link counts are zero.

When an NFS file is unlinked its link count isn't reduced until
the last open instance is closed on either the NFS clients or the
NFS.  That's a consequence of NFS statelessness and leads to the
occasional presence of files with names of the form .nfsxxxx you
may have noticed.

Should nlink find its test file on an NFS file system, it disables
the unlink section of its tests and issues a warning.  It also
issues a hint that the test file path can be named via the -p option
to give a test file location that isn't on an NFS file system.

This test can't be run on Darwin, because insufficient file system
link count information is available to lsof there.

Because some UNIX dialects delay the reporting of a link count
update after a file has been unlinked, LTnlink may not get its
expected response from lsof for a while after the test file has
been unlinked.  In that cause LTnlink may delay for up to a minute,
calling lsof once every two seconds and displaying a "waiting for
link count update: ..." message.

Run this test:

    $ ./LTnlink [-p <path>]

Environment variables: LT_LSOF_PATH defines the path to the lsof
		       executable.  (The default is ../lsof.)

G.7. LTsock, Test IPv4 Sockets
==============================

This is a test in the standard test group.

This test uses lsof to locate open IPv4 socket files that the test
has created itself.  The test opens a server socket, then forks a
child process to connect to that socket.  After both are running,
the test uses lsof to find the open socket files at their known
host and port addresses.

Run this test:

    $ ./LTsock

Environment variables: LT_LSOF_PATH defines the path to the lsof
		       executable.  (The default is ../lsof.)

G.8. LTszoff, Test Sizes and Offsets for Small (< 32 bit) Files
===============================================================

This is a test in the standard test group.

This test checks lsof's reporting of file size and offset for small
(< 32 bits) files.

It creates a test file in the current working directory named
tests/config.LTszoff<PID>.  PID is the Process ID of the test
process.

LTszoff can't test file offset reporting on Linux, because its
/proc file system doesn't report them to lsof.

Run this test:

    $ ./LTszoff [-p <path>]

Environment variables: LT_LSOF_PATH defines the path to the lsof
		       executable.  (The default is ../lsof.)

G.9.  LTunix, Test UNIX Domain Sockets
======================================

This is a test in the standard test group.

This test checks lsof's reporting of UNIX domain sockets.

The test creates a pair of UNIX domain sockets and uses bind(2) to
associate the file system names config.LT0U<PID> (client) and
config.LT1U<PID> (server) with them.  (PID is the test process ID.)
The test then uses lsof to find the two open UNIX domain socket
files.

Run this test:

    $ ./LTunix

Environment variables: LT_LSOF_PATH defines the path to the lsof
		       executable.  (The default is ../lsof.)


Appendix A, Test Files
======================

These files may be created by suite tests.

			Created
    ./tests Name	by Test	    Use
    ============	=======	    ===

    config.LTbifg**     LTbigf      to test lsof's large file size
				    and offset reporting

    config.LTlock*	LTlock	    for locking tests

    config.LTnfs*	LTnfs	    for NFS tests

    config.LTnlink*	LTnlink	    for link count tests

    config.LTszoff*     LTszoff     for small file size and and
				    offset reporting

    config.LT[01]U*     LTunix      two UNIX domain sockets, used
				    to determine if lsof can report
				    their open instances properly


Appendix B, Test Validations
============================

This appendix lists the UNIX dialects and their versions where I
have validated the test suite.  The list indicates the particular
tests I was unable to run, mostly LTnfs because the test systems
I used had no NFS file systems mounted.

The information in the following table is encoded in a test data
base file, tests/TestDB, as lsof dialect footprints, using the
tests compiler options written to tests/config.cflags by the lsof
Configure script.  See "B.2. Test Data Base and Scripts" for more
information on the test data base, lsof dialect footprints, and
the scripts that support them.

    UNIX
    Dialect	  Dialect Description		Untested Tests
    ======= 	  ===================		==============
    AIX		  4.3.3, Power, cc
		  5.1.1, Power-32, cc
		  5.1.1, Power-64, cc
    BSDI	  4.1, gcc
    Darwin        1.4, gcc                      Darwin lsof doesn't
						have adequate support
						to allow the LTdnlc,
						LTlock, LTnfs, and
						LTnlink tests to run.
    FreeBSD       4.5, gcc
		  5.0, gcc
    DEC OSF/1	  4.0, cc
    HP-UX         11.00-32, ANSI-C		LTbigf, LTnfs
		  11.00-64, ANSI-C
		  11.11, ANSI-C			LTnfs
    Linux         2.4.12-696            	LTbigf, no offset tests
						LTszoff, no offset tests
    OSR           5.04, cc              	LTnfs
		  5.06, cc              	LTnfs
    NEXTSTEP      3.1, gcc                   	LTnfs
    NetBSD        1.4.1, Alpha, gcc          	LTnfs
		  1.5ZX, i386, gcc           	LTnfs
    OpenBSD       3.0, gcc
    OpenUNIX	  8.0, cc			LTnfs
    Solaris       2.6, cc			LTnfs
		  2.6, gcc			LTnfs
		  7-32, cc			LTnfs
		  7-32, gcc			LTnfs
		  8-64, cc
		  9-64, Beta-Refresh, cc
		  9-64, Beta-Refresh, gcc
    Tru64 UNIX    5.0, cc
		  5.1, cc
    UnixWare      7.1.1, NSC, cc            	LTnfs

If you are able to run the test suite on dialect versions other
than the ones listed above, please send e-mail to <abe@purdue.edu>,
indicating the dialect version where you were able to run the test
suite.  Please run the Add2TestDB script send me the lsof dialect
footprint that it reports.

If you encounter problems compiling the tests or running them on
a dialect version listed above, please send e-mail to <abe@purdue.edu>,
naming the dialect version and providing the output from the lsof
Configure script and make operation.


Appendix C, Test Failures
=========================

I was unable to make the test suite run on the following dialects.

    UNIX Dialect
    and Description	 Failure
    ======a=========	 =======
    HP-UX 11-64, gcc     64 bit gcc 3.0 didn't compile the LTsock
			 test correctly on my 64 bit HP-UX 11 test
			 system.


Vic Abell <abe@purdue.edu>
April 18, 2002
