]> git.ipfire.org Git - thirdparty/make.git/commitdiff
tests: Run each file in a separate directory
authorPaul Smith <psmith@gnu.org>
Sun, 2 Apr 2023 21:32:09 +0000 (17:32 -0400)
committerPaul Smith <psmith@gnu.org>
Sun, 2 Apr 2023 21:32:09 +0000 (17:32 -0400)
Avoid cross-contamination between test files by creating a new
working directory for each file, and setting it as the current
directory before starting the tests in that file.

Rename the test output as tNNN.{base,log,diff,mk} where NNN is
a test number starting with 001 for the first test.  It is
slightly more annoying to find diff files since you can't use
autocomplete directly but it is simpler to match things.

Detect the source directory as the location of the test_driver.pl
script, so remove the separate -srcdir option.

* Makefile.am: Remove hacks to create symlinks when building
out-of-tree, and remove -srcdir option from run_make_tests.
* tests/test_driver.pl: Locate $srcpath based on __FILE__, then
compute $toppath as its parent.  Set $scriptpath under $srcpath
and $workpath under the current directory.  Toss $*_filename
and modify get_logfile() etc. to use the suffix directly.  Add
a chdir() around the invocation of the test.
* tests/run_make_tests.pl: Throw out the -srcdir option and use
$srcpath set in test_driver.pl.  The #WORK# helper is no longer
useful so remove it.  Set #PWD# to the current working dir. Always
search the local directory and $srcpath for config-flags.pm.
Use $srcpath for finding the thelp.pl script.
* tests/scripts/features/vpath: Don't put things in work/ as it
is no longer a subdirectory.
* tests/scripts/features/vpathgpath: Ditto.
* tests/scripts/features/vpathplus: Ditto.
* tests/scripts/misc/general1: Ditto.
* tests/scripts/misc/general2: Ditto.
* tests/scripts/options/dash-k: Ditto.
* tests/scripts/options/symlinks: Use $testpath as the working
directory.
* tests/scripts/variables/GNUMAKEFLAGS: Use the test helper to
display env var values (grepping for GNUMAKEFLAGS finds extra things
now that it is our current working directory).

Makefile.am
tests/run_make_tests.pl
tests/scripts/features/vpath
tests/scripts/features/vpathgpath
tests/scripts/features/vpathplus
tests/scripts/misc/general1
tests/scripts/misc/general2
tests/scripts/options/dash-k
tests/scripts/options/symlinks
tests/scripts/variables/GNUMAKEFLAGS
tests/test_driver.pl

index 05be34539759cf003b50d51bf5ee5b70388b8e54..23a48e4729039fd5f57edb731a72367d5b68b2f0 100644 (file)
@@ -152,8 +152,6 @@ check-local: check-regression
 # > check-regression
 #
 # Look for the make test suite, and run it if found and we can find perl.
-# If we're building outside the tree, we use symlinks to make a local copy of
-# the test suite.  Unfortunately the test suite itself isn't localizable yet.
 #
 MAKETESTFLAGS =
 
@@ -177,20 +175,12 @@ rand_char  = substr(c,int(rand()*36),1)
 rand_string = $(AWK) 'BEGIN{srand(); $(rand_value); print $(rand_char) "" $(rand_char) "" $(rand_char) "" $(rand_char);}'
 
 check-regression: tests/config-flags.pm
-       @rm -f $(testfiles)
-       @if test -f '$(top_srcdir)/tests/run_make_tests'; then \
+       $(AM_V_at) rm -f $(testfiles)
+       $(AM_V_at) if test -f '$(top_srcdir)/tests/run_make_tests.pl'; then \
          ulimit -n 128; \
          if $(PERL) -v >/dev/null 2>&1; then \
-           case `cd '$(top_srcdir)'; pwd` in `pwd`) : ;; \
-             *) test -d tests || mkdir tests; \
-                rm -f srctests; \
-                if ln -s '$(top_srcdir)/tests' srctests; then \
-                  for f in run_make_tests run_make_tests.pl test_driver.pl scripts thelp.pl; do \
-                    rm -f tests/$$f; ln -s ../srctests/$$f tests; \
-                  done; fi ;; \
-           esac; \
-           echo "cd tests && $(PERL) $(PERLFLAGS) ./run_make_tests.pl -srcdir $(abs_top_srcdir) -make $(GMK_OUTDIR)/make$(EXEEXT) $(MAKETESTFLAGS)"; \
-           (cd tests && $(PERL) $(PERLFLAGS) ./run_make_tests.pl -srcdir '$(abs_top_srcdir)' -make '$(GMK_OUTDIR)/make$(EXEEXT)' $(MAKETESTFLAGS); echo $$? >.test-result) 2>&1 | tee $(testlog); \
+           echo "cd tests && $(PERL) $(PERLFLAGS) $(abs_top_srcdir)/tests/run_make_tests.pl -make $(GMK_OUTDIR)/make$(EXEEXT) $(MAKETESTFLAGS)"; \
+           (cd tests && $(PERL) $(PERLFLAGS) '$(abs_top_srcdir)/tests/run_make_tests.pl' -make '$(GMK_OUTDIR)/make$(EXEEXT)' $(MAKETESTFLAGS); echo $$? >.test-result) 2>&1 | tee $(testlog); \
            export TAR_OPTIONS='$(filter-out --sort%,$(TAR_OPTIONS))'; \
            er=$$(cat $(testresult)); if test "$$er" -ne 0; then \
              dirnm="$(errorpre)-$$($(rand_string))"; fnm="$$dirnm.tar.gz"; \
index 012bd66d7213bdbb03b730694f051494e074f327..b43a80c66b4ac3e228ac112ba264480f9f047317 100644 (file)
@@ -56,16 +56,6 @@ $memcheck_args = '--num-callers=15 --tool=memcheck --leak-check=full --suppressi
 $massif_args = '--num-callers=15 --tool=massif --alloc-fn=xmalloc --alloc-fn=xcalloc --alloc-fn=xrealloc --alloc-fn=xstrdup --alloc-fn=xstrndup';
 $pure_log = undef;
 
-# The location of the GNU Make source directory
-$srcdir = undef;
-$fqsrcdir = undef;
-$srcvol = undef;
-
-# The location of the build directory
-$blddir = undef;
-$fqblddir = undef;
-$bldvol = undef;
-
 $make_path = undef;
 @make_command = ();
 
@@ -126,15 +116,6 @@ sub valid_option
        return 1;
    }
 
-   if ($option =~ /^-srcdir$/i) {
-       $srcdir = shift @argv;
-       if (! -f File::Spec->catfile($srcdir, 'src', 'gnumake.h')) {
-           print "$option $srcdir: Not a valid GNU Make source directory.\n";
-           exit 1;
-       }
-       return 1;
-   }
-
    if ($option =~ /^-all([-_]?tests)?$/i) {
        $all_tests = 1;
        return 1;
@@ -179,13 +160,13 @@ $helptool = undef;
 
 sub subst_make_string
 {
+    my $wd = cwd();
     local $_ = shift;
     $makefile and s/#MAKEFILE#/$makefile/g;
     s/#MAKEPATH#/$mkpath/g;
     s/#MAKE#/$make_name/g;
     s/#PERL#/$perl_name/g;
-    s/#PWD#/$cwdpath/g;
-    s/#WORK#/$workdir/g;
+    s/#PWD#/$wd/g;
     s/#HELPER#/$perl_name $helptool/g;
     return $_;
 }
@@ -372,7 +353,7 @@ sub run_make_with_options {
 sub print_usage
 {
    &print_standard_usage ("run_make_tests",
-                          "[-make MAKE_PATHNAME] [-srcdir SRCDIR] [-memcheck] [-massif]",);
+                          "[-make MAKE_PATHNAME] [-memcheck] [-massif]",);
 }
 
 sub print_help
@@ -380,8 +361,6 @@ sub print_help
    &print_standard_help (
         "-make",
         "\tYou may specify the pathname of the copy of make to run.",
-        "-srcdir",
-        "\tSpecify the make source directory.",
         "-valgrind",
         "-memcheck",
         "\tRun the test suite under valgrind's memcheck tool.",
@@ -525,55 +504,21 @@ sub set_more_defaults
 {
   my $string;
 
-  # Now that we have located make_path, locate the srcdir and blddir
-  my ($mpv, $mpd, $mpf) = find_prog($make_path);
-
-  # We have a make program so try to compute the blddir.
-  if ($mpd) {
-    my $f = File::Spec->catpath($mpv, File::Spec->catdir($mpd, 'tests'), 'config-flags.pm');
-    if (-f $f) {
-      $bldvol = $mpv;
-      $blddir = $mpd;
-    }
-  }
-
-  # If srcdir wasn't provided on the command line, try to find it.
-  if (! $srcdir && $blddir) {
-    # See if the blddir is the srcdir
-    my $f = File::Spec->catpath($bldvol, File::Spec->catdir($blddir, 'src'), 'gnumake.h');
-    if (-f $f) {
-      $srcdir = $blddir;
-      $srcvol = $bldvol;
-    }
-  }
+  # Try to find and load config-flags.pm.  They may be in the local directory
+  # or in the $srcpath if we're remote.
 
-  if (! $srcdir) {
-    # Not found, see if our parent is the source dir
-    my $f = File::Spec->catpath($cwdvol, File::Spec->catdir(File::Spec->updir(), 'src'), 'gnumake.h');
-    if (-f $f) {
-      $srcdir = File::Spec->updir();
-      $srcvol = $cwdvol;
-    }
+  my $d = $cwd;
+  my $cfg = File::Spec->catfile($d, 'config-flags.pm');
+  if (! -f $cfg) {
+      # Nope, so look in the srcpath
+      my $d = $srcpath;
+      $cfg = File::Spec->catfile($d, 'config-flags.pm');
   }
 
-  # If we have srcdir but not blddir, set them equal
-  if ($srcdir && !$blddir) {
-    $blddir = $srcdir;
-    $bldvol = $srcvol;
-  }
+  -f $cfg or die "Can't locate config-flags.pm in $cwd" . ($cwd eq $srcpath ? '' : " or $srcpath") . "\n";
 
-  # Load the config flags
-  if (!$blddir) {
-    warn "Cannot locate config-flags.pm (no blddir)\n";
-  } else {
-    my $f = File::Spec->catpath($bldvol, File::Spec->catdir($blddir, 'tests'), 'config-flags.pm');
-    if (! -f $f) {
-      warn "Cannot locate $f\n";
-    } else {
-      unshift(@INC, File::Spec->catpath($bldvol, File::Spec->catdir($blddir, 'tests'), ''));
-      require "config-flags.pm";
-    }
-  }
+  unshift(@INC, $d);
+  require "config-flags.pm";
 
   # Find the full pathname of Make.  For DOS systems this is more
   # complicated, so we ask make itself.
@@ -623,27 +568,14 @@ sub set_more_defaults
   # start with a slash, but contains one).  Thanks for the
   # clue, Roland.
 
-  if ($mpd && !File::Spec->file_name_is_absolute($make_path) && $cwdvol == $mpv) {
+  if ($mpd && !File::Spec->file_name_is_absolute($make_path) && $cwdvol eq $mpv) {
      $mkpath = File::Spec->catpath($cwdvol, File::Spec->catdir($cwd, $mpd), $mpf);
   } else {
      $mkpath = $make_path;
   }
 
-  # Not with the make program, so see if we can get it out of the makefile
-  if (! $srcdir && open(MF, '<', File::Spec->catfile(File::Spec->updir(), 'Makefile'))) {
-    local $/ = undef;
-    $_ = <MF>;
-    close(MF);
-    /^abs_srcdir\s*=\s*(.*?)\s*$/m;
-    -f File::Spec->catfile($1, 'src', 'gnumake.h') and $srcdir = $1;
-  }
-
-  # At this point we should have srcdir and blddir: get fq versions
-  $fqsrcdir = File::Spec->rel2abs($srcdir);
-  $fqblddir = File::Spec->rel2abs($blddir);
-
   # Find the helper tool
-  $helptool = File::Spec->catfile($fqsrcdir, 'tests', 'thelp.pl');
+  $helptool = File::Spec->catfile($srcpath, 'thelp.pl');
 
   # It's difficult to quote this properly in all the places it's used so
   # ensure it doesn't need to be quoted.
index 7c034b5eba1ca9269b1b58926efe1c8eddb4442c..3afffc53a3741293e9375c1bf2f6621c171241ed 100644 (file)
@@ -4,18 +4,20 @@ $description = "Test vpath for particular classes of filenames.";
 
 $details = "";
 
-@files_to_touch = ("$workdir${pathsep}main.c","$workdir${pathsep}defs.h",
-                   "$workdir${pathsep}kbd.c","$workdir${pathsep}command.h",
-                   "$workdir${pathsep}commands.c","$workdir${pathsep}display.c",
-                   "$workdir${pathsep}buffer.h","$workdir${pathsep}insert.c",
-                   "$workdir${pathsep}command.c");
+mkdir('work');
+
+@files_to_touch = ("work${pathsep}main.c","work${pathsep}defs.h",
+                   "work${pathsep}kbd.c","work${pathsep}command.h",
+                   "work${pathsep}commands.c","work${pathsep}display.c",
+                   "work${pathsep}buffer.h","work${pathsep}insert.c",
+                   "work${pathsep}command.c");
 
 &touch(@files_to_touch);
 
 run_make_test(q!
 vpath %.c foo
-vpath %.c #WORK#
-vpath %.h #WORK#
+vpath %.c work
+vpath %.h work
 objects = main.o kbd.o commands.o display.o insert.o
 edit: $(objects) ; @echo cc -o $@ $^
 main.o : main.c defs.h ; @echo cc -c $(firstword $^)
@@ -24,7 +26,7 @@ commands.o : command.c defs.h command.h ; @echo cc -c commands.c
 display.o : display.c defs.h buffer.h ; @echo cc -c display.c
 insert.o : insert.c defs.h buffer.h ; @echo cc -c insert.c
 !,
-    '', "cc -c $workdir${pathsep}main.c\ncc -c kbd.c\ncc -c commands.c\n"
+    '', "cc -c work${pathsep}main.c\ncc -c kbd.c\ncc -c commands.c\n"
         ."cc -c display.c\ncc -c insert.c\n"
         ."cc -o edit main.o kbd.o commands.o display.o insert.o\n");
 
@@ -50,11 +52,11 @@ rmdir('vpath-d');
 # Test VPATH vs vpath
 
 run_make_test(q!
-VPATH = #WORK#:#PWD#
+VPATH = work:#PWD#
 vpath %.c foo
-vpath %.c #WORK#
+vpath %.c work
 vpath %.c #PWD#
-vpath %.h #WORK#
+vpath %.h work
 vpath %.c
 vpath
 all: ; @echo ALL IS WELL
index 5c5996c6969aa32b5b891b22a6262d48c6babd32..b76c5b350a1041c1114ddd9943a36a55d51a6dc5 100644 (file)
@@ -3,7 +3,9 @@ $description = "Tests VPATH+/GPATH functionality.";
 
 $details = "";
 
-$VP = "$workdir$pathsep";
+mkdir('work');
+
+$VP = "work$pathsep";
 
 open(MAKEFILE,"> $makefile");
 
index da169839085aa40224bc9883dcffd1a3d0cd3112..9e935c54dc0ca4c605d42fee9657118a2df960c6 100644 (file)
@@ -3,7 +3,9 @@ $description = "Tests the new VPATH+ functionality added in 3.76.";
 
 $details = "";
 
-$VP = "$workdir$pathsep";
+mkdir('work');
+
+$VP = "work$pathsep";
 
 @touchedfiles = ();
 
index 352fc6adac4c14b0be1907d9c51735dce520c246..098956ba79287f5b430e5c596246a381c225eb86 100644 (file)
@@ -8,7 +8,7 @@ It also tests the simple definition of VPATH.";
 open(MAKEFILE,"> $makefile");
 
 print MAKEFILE <<EOF;
-VPATH = $workdir
+VPATH = work
 edit:  main.o kbd.o commands.o display.o \\
        insert.o
 \t\@echo cc -o edit main.o kbd.o commands.o display.o \\
@@ -28,11 +28,12 @@ EOF
 close(MAKEFILE);
 
 
-@files_to_touch = ("$workdir${pathsep}main.c","$workdir${pathsep}defs.h",
-               "$workdir${pathsep}kbd.c","$workdir${pathsep}command.h",
-               "$workdir${pathsep}commands.c","$workdir${pathsep}display.c",
-               "$workdir${pathsep}buffer.h","$workdir${pathsep}insert.c",
-              "$workdir${pathsep}command.c");
+mkdir('work');
+@files_to_touch = ("work${pathsep}main.c","work${pathsep}defs.h",
+               "work${pathsep}kbd.c","work${pathsep}command.h",
+               "work${pathsep}commands.c","work${pathsep}display.c",
+               "work${pathsep}buffer.h","work${pathsep}insert.c",
+               "work${pathsep}command.c");
 
 &touch(@files_to_touch);
 
index fb5c3aafd90c5c960eab8a818c329b1a3c37bc35..f93006c05cf5d5642697512f16808c11e2c57f7d 100644 (file)
@@ -10,7 +10,7 @@ open(MAKEFILE,"> $makefile");
 # The contents of the Makefile ...
 
 print MAKEFILE <<EOF;
-VPATH = $workdir
+VPATH = work
 objects = main.o kbd.o commands.o display.o insert.o
 edit:  \$(objects)
 \t\@echo cc -o edit \$(objects)
@@ -29,11 +29,12 @@ EOF
 close(MAKEFILE);
 
 
-@files_to_touch = ("$workdir${pathsep}main.c","$workdir${pathsep}defs.h",
-               "$workdir${pathsep}kbd.c","$workdir${pathsep}command.h",
-               "$workdir${pathsep}commands.c","$workdir${pathsep}display.c",
-               "$workdir${pathsep}buffer.h","$workdir${pathsep}insert.c",
-              "$workdir${pathsep}command.c");
+mkdir('work');
+@files_to_touch = ("work${pathsep}main.c","work${pathsep}defs.h",
+               "work${pathsep}kbd.c","work${pathsep}command.h",
+               "work${pathsep}commands.c","work${pathsep}display.c",
+               "work${pathsep}buffer.h","work${pathsep}insert.c",
+               "work${pathsep}command.c");
 
 &touch(@files_to_touch);
 
index fec630c3605e4717ab6cdc019fb8e422435bda17..05db28acbc9bb9b8e32635d33a3b2a42f6eea8be 100644 (file)
@@ -16,7 +16,7 @@ open(MAKEFILE,"> $makefile");
 # The Contents of the MAKEFILE ...
 
 print MAKEFILE <<EOF;
-VPATH = $workdir
+VPATH = work
 edit:  main.o kbd.o commands.o display.o
 \t\@echo cc -o edit main.o kbd.o commands.o display.o
 
@@ -38,11 +38,12 @@ EOF
 close(MAKEFILE);
 
 
-@files_to_touch = ("$workdir${pathsep}main.c","$workdir${pathsep}defs.h",
-               "$workdir${pathsep}command.h",
-               "$workdir${pathsep}commands.c","$workdir${pathsep}display.c",
-               "$workdir${pathsep}buffer.h",
-               "$workdir${pathsep}command.c");
+mkdir('work');
+@files_to_touch = ("work${pathsep}main.c","work${pathsep}defs.h",
+               "work${pathsep}command.h",
+               "work${pathsep}commands.c","work${pathsep}display.c",
+               "work${pathsep}buffer.h",
+               "work${pathsep}command.c");
 
 &touch(@files_to_touch);
 
index 83dc84fb924a3e5b8eb325dff1cd992b736f925d..8886b2fc74621b3f6a99cf810450ac384581a04e 100644 (file)
@@ -15,8 +15,9 @@ use File::Spec;
 &utouch(-10, 'dep');
 &utouch(-5, 'targ');
 
-$dirnm = (File::Spec->splitdir($cwddir))[-1];
-symlink(File::Spec->catfile(File::Spec->updir(), $dirnm, 'dep'), 'sym');
+my $dirnm = (File::Spec->splitdir($testpath))[-1];
+my $dep = File::Spec->catfile(File::Spec->updir(), $dirnm, 'dep');
+symlink($dep, 'sym') or die "Cannot create symlink sym -> $dep\n";
 
 # Without -L, nothing should happen
 # With -L, it should update targ
index 6dc9fd8c8e8d50f970208d5744313dd3907a93f4..69bb05479010b1e5d1d489011c662f0e66c1f378 100644 (file)
@@ -41,13 +41,13 @@ unlink('x.mk');
 
 # Ensure that we don't add GNUMAKEFLAGS to the environment if it's not there
 run_make_test(q!
-all: ; @env | grep GNUMAKEFLAGS; true
+all: ; @#HELPER# env GNUMAKEFLAGS
 !,
-              '', '');
+              '', 'GNUMAKEFLAGS=<unset>');
 
 $ENV{GNUMAKEFLAGS} = '-Itst/bad';
 run_make_test(q!
-all: ; @env | grep GNUMAKEFLAGS; true
+all: ; @#HELPER# env GNUMAKEFLAGS
 !,
               '', 'GNUMAKEFLAGS=');
 
index b3a8cd2cb017e94cb7905114f01439d1b4907a37..6ddce4f9e377573073af12a9473c4ea6373d28c4 100644 (file)
@@ -35,6 +35,12 @@ use Cwd;
 use File::Spec;
 use File::Temp;
 
+$debug = 0;                 # debug flag
+$profile = 0;               # profiling flag
+$verbose = 0;               # verbose mode flag
+$detail = 0;                # detailed verbosity
+$keep = 0;                  # keep temp files around
+
 # The number of test categories we've run
 $categories_run = 0;
 # The number of test categroies that have passed
@@ -56,6 +62,9 @@ $osname = undef;
 $vos = undef;
 $pathsep = undef;
 
+$testee = undef;
+$testee_version = undef;
+
 # Yeesh.  This whole test environment is such a hack!
 $test_passed = 1;
 
@@ -234,11 +243,22 @@ sub toplevel
   $tmpfilesuffix = "t";       # the suffix used on tmpfiles
   $default_output_stack_level = 0;  # used by attach_default_output, etc.
   $default_input_stack_level = 0;   # used by attach_default_input, etc.
-  $cwd = ".";                 # don't we wish we knew
-  $cwdslash = "";             # $cwd . $pathsep, but "" rather than "./"
 
   &get_osname;  # sets $osname, $vos, $pathsep, and $short_filenames
 
+  # Locate the test directory.  It's the one that contains this script.
+  my @sp = File::Spec->splitpath(__FILE__);
+  $srcpath = File::Spec->canonpath(File::Spec->catpath($sp[0], $sp[1], ''));
+
+  # Locate the top source directory.
+  $toppath = File::Spec->rel2abs(File::Spec->updir(), $srcpath);
+
+  $cwd = cwd();
+
+  $workpath = "$workdir";
+
+  $scriptpath = $srcpath eq $cwd ? $scriptdir : File::Spec->catdir($srcpath, $scriptdir);
+
   $perl_name = which($perl_name);
 
   # See if we have a diff
@@ -256,7 +276,6 @@ sub toplevel
   $temppath = File::Spec->rel2abs($tempdir);
 
   if (-d $temppath) {
-    print "Clearing $temppath...\n";
     &remove_directory_tree("$temppath/")
       or &error ("Couldn't wipe out $temppath: $!\n");
   } else {
@@ -273,14 +292,11 @@ sub toplevel
   # Replace the environment with the new one
   resetENV();
 
-  $workpath = "$cwdslash$workdir";
-  $scriptpath = "$cwdslash$scriptdir";
-
   &set_more_defaults;  # suite-defined
 
   &print_banner;
 
-  if ($osname eq 'VMS' && $cwdslash eq "") {
+  if ($osname eq 'VMS' && $scriptpath eq $scriptdir) {
     # Porting this script to VMS revealed a small bug in opendir() not
     # handling search lists correctly when the directory only exists in
     # one of the logical_devices.  Need to find the first directory in
@@ -297,6 +313,7 @@ sub toplevel
     }
   }
 
+  print "Finding tests in $scriptpath...\n";
   if (-d $workpath) {
     print "Clearing $workpath...\n";
     &remove_directory_tree("$workpath/")
@@ -310,7 +327,7 @@ sub toplevel
   }
 
   if (@TESTS) {
-    print "Making work dirs...\n";
+    print "Creating dirs in $workpath...\n";
     foreach $test (@TESTS) {
       if ($test =~ /^([^\/]+)\//) {
         $dir = $1;
@@ -321,11 +338,12 @@ sub toplevel
       }
     }
   } else {
-    print "Finding tests...\n";
+    print "Searching for tests...\n";
     opendir (SCRIPTDIR, $scriptpath)
         or &error ("Couldn't opendir $scriptpath: $!\n");
     @dirs = grep (!/^(\..*|CVS|RCS)$/, readdir (SCRIPTDIR) );
     closedir (SCRIPTDIR);
+    print "Creating dirs in $workpath...\n";
     foreach my $dir (@dirs) {
       next if ($dir =~ /^(\..*|CVS|RCS)$/ || ! -d "$scriptpath/$dir");
       push (@rmdirs, $dir);
@@ -355,6 +373,7 @@ sub toplevel
   foreach my $dir (@rmdirs) {
     rmdir ("$workpath/$dir");
   }
+  rmdir ($workpath);
 
   rmdir ($temppath);
 
@@ -368,7 +387,7 @@ sub toplevel
     print "s" unless $total_tests_failed == 1;
     print " in $categories_failed Categor";
     print ($categories_failed == 1 ? "y" : "ies");
-    print " Failed (See .$diffext* files in $workdir dir for details) :-(\n\n";
+    print " Failed (See .$diffext files in $workdir dir for details) :-(\n\n";
     return 0;
   } elsif ($some_test_failed) {
       # Something failed but no tests were marked failed... probably a syntax
@@ -596,7 +615,7 @@ sub run_all_tests
     $diffext = 'diff';
     $baseext = 'base';
     $runext = 'run';
-    $extext = '.';
+    $extext = $osname eq 'VMS' ? '_' : '.';
   }
 
   $lasttest = '';
@@ -613,18 +632,16 @@ sub run_all_tests
     $details = "";
     $old_makefile = undef;
     $testname =~ s/^$scriptpath$pathsep//;
-    $perl_testname = "$scriptpath$pathsep$testname";
     $testname =~ s/(\.pl|\.perl)$//;
-    $testpath = "$workpath$pathsep$testname";
-    $extext = '_' if $osname eq 'VMS';
-    $log_filename = "$testpath.$logext";
-    $diff_filename = "$testpath.$diffext";
-    $base_filename = "$testpath.$baseext";
-    $run_filename = "$testpath.$runext";
-    $tmp_filename = "$testpath.$tmpfilesuffix";
 
+    $perl_testname = "$scriptpath$pathsep$testname";
     -f $perl_testname or die "Invalid test: $testname\n\n";
 
+    $testpath = "$workpath$pathsep$testname";
+
+    remove_directory_tree($testpath);
+    mkdir($testpath, 0777) or &error("Couldn't mkdir $testpath: $!\n", 1);
+
     setup_for_test();
 
     $output = "........................................................ ";
@@ -637,7 +654,9 @@ sub run_all_tests
     $tests_passed = 0;
 
     # Run the test!
+    chdir($testpath) or error("Can't change to $testpath: $!\n", 1);
     $code = do $perl_testname;
+    chdir($cwd) or error("Can't change back to $cwd: $!\n", 1);
 
     # Reset STDIN from the copy in case it was changed
     open(STDIN, "<&INCOPY");
@@ -685,12 +704,8 @@ sub run_all_tests
       $status = "ok     ($tests_passed passed)";
 
       # Clean up
-      for ($i = $num_of_tmpfiles; $i; $i--) {
-        rmfiles($tmp_filename . num_suffix($i));
-      }
-      for ($i = $num_of_logfiles ? $num_of_logfiles : 1; $i; $i--) {
-        rmfiles($log_filename . num_suffix($i));
-        rmfiles($base_filename . num_suffix($i));
+      if (!$keep) {
+        remove_directory_tree($testpath);
       }
     }
 
@@ -1493,19 +1508,26 @@ sub compare_dir_tree
   return !$bogus;
 }
 
-# this subroutine generates the numeric suffix used to keep tmp filenames,
-# log filenames, etc., unique.  If the number passed in is 1, then a null
-# string is returned; otherwise, we return ".n", where n + 1 is the number
-# we were given.
+# this subroutine generates the prefix name used to keep tmp filenames,
+# log filenames, etc., unique.
 
-sub num_suffix
+sub get_prefix
 {
   my ($num) = @_;
-  if (--$num > 0) {
-    return "$extext$num";
-  }
+  return sprintf("t%03d.", $num);
+}
 
-  return "";
+# just like logfile, only a generic tmp filename for use by the test.
+# they are automatically cleaned up unless -keep was used, or the test fails.
+# Pass an argument of 1 to return the same filename as the previous call.
+
+sub get_tmpfile
+{
+  my ($no_increment) = @_;
+
+  $num_of_tmpfiles += !$no_increment;
+
+  return (&get_prefix ($num_of_tmpfiles) . $tmpfilesuffix);
 }
 
 # This subroutine returns a log filename with a number appended to
@@ -1522,7 +1544,7 @@ sub get_logfile
 
   $num_of_logfiles += !$no_increment;
 
-  return ($log_filename . &num_suffix ($num_of_logfiles));
+  return (&get_prefix ($num_of_logfiles) . $logext);
 }
 
 # This subroutine returns a base (answer) filename with a number
@@ -1532,7 +1554,7 @@ sub get_logfile
 
 sub get_basefile
 {
-  return ($base_filename . &num_suffix ($num_of_logfiles));
+  return (&get_prefix ($num_of_logfiles) . $baseext);
 }
 
 # This subroutine returns a difference filename with a number appended
@@ -1541,7 +1563,7 @@ sub get_basefile
 
 sub get_difffile
 {
-  return ($diff_filename . &num_suffix ($num_of_logfiles));
+  return (&get_prefix ($num_of_logfiles) . $diffext);
 }
 
 # This subroutine returns a command filename with a number appended
@@ -1550,20 +1572,7 @@ sub get_difffile
 
 sub get_runfile
 {
-  return ($run_filename . &num_suffix ($num_of_logfiles));
-}
-
-# just like logfile, only a generic tmp filename for use by the test.
-# they are automatically cleaned up unless -keep was used, or the test fails.
-# Pass an argument of 1 to return the same filename as the previous call.
-
-sub get_tmpfile
-{
-  my ($no_increment) = @_;
-
-  $num_of_tmpfiles += !$no_increment;
-
-  return ($tmp_filename . &num_suffix ($num_of_tmpfiles));
+  return (&get_prefix ($num_of_logfiles) . $runext);
 }
 
 1;