#!/usr/bin/perl -w
#
# Perlscript for testing XPLAB comparing all result files in a directory.
#
# Revision: 09.01.2005 E.Sack
#
use strict;
use vars qw($opt_h), qw($opt_u), qw($sum_str), qw($err_str);
use vars qw($xplab), qw($good_str), qw($warn_str), qw($bad_str), qw($update_str);
use vars qw($cmd_ext), qw($opt_k), qw($opt_l);
use Getopt::Std;
use FileHandle;

sub time_diff ($$$$$);
sub print_test_header ($$);
sub pattern_matching1 (@);
sub single_dot_test (@);
sub chain_test (@);
sub connect_test (@);
sub sequence_test (@);
sub separation_test (@);
sub cluster_test (@);
sub tiles_test (@);
sub uni_test (@);

my ($ls, @als, $dir, $start_test_time, $testnumber);
my (@entry, $single_test);

$xplab = "../src/xplab";                            # XPLAB filespec
$good_str = "PASS";
$bad_str =  "FAIL";
$warn_str = "WARN";
$update_str = "COPY";
$sum_str = "TOTAL";
$err_str = "ERROR";
$cmd_ext = "2>/dev/null";                           # redirect error messages
$start_test_time = time;
$testnumber = 0;
$single_test = 0;

autoflush STDOUT;
$opt_h = 0; 
$opt_u = 0; 
$opt_k = 0; 
$opt_l = 0; 

if (!getopts('huzFkl')) {
  print "\n please type `xrun_tp -h'\n\n";
  die;
}

if ($opt_h) {
  print "\n   xrun_tp - Test script for XPLAB test cases\n\n",
        "   xrun_tp [-h]\n",
        "   xrun_tp [-k] [-l] [-u] [n]\n\n",
        "           n - run test number n only\n\n",
        "           -h this help\n",
        "           -k keep temporary files created by XPLAB\n",
        "           -l list all tests\n",
        "           -u update files causing warnings (if no fails)\n",
        "\n";
  exit;
}

$single_test = shift(@ARGV) if ($#ARGV >= 0);

# generate ID for test run
@als = split / +/, `ls -l $xplab`;
splice(@als, 0, 4);
$ls = join ' ', @als;
chop $ls;
$ls = "(ID: " . $ls . ")";

print "\nXPLAB Test Cases $ls\n";
print "*** Reportfiles of the testcases will be overwritten ***\n" if $opt_u;

chop($dir = `pwd`);
print "Directory: $dir \n\n";

# read in an array of all directory entries, example from PERLFUNC.
opendir(DIR, $dir) || die "can't opendir $dir ... $!";
@entry = grep { -f "$dir/$_" } readdir(DIR);
closedir DIR;

###### testcases ###########################################################

single_dot_test ++$testnumber, @entry;                      # implicit input
chain_test ++$testnumber, @entry;                           # implicit input
connect_test ++$testnumber, @entry;                         # implicit input
sequence_test ++$testnumber, @entry;                        # implicit input
separation_test ++$testnumber, @entry;                      # implicit input

uni_test (++$testnumber, "slant test",
          ["slant1", "screen_db", "SlantTest.cfg"],         # explicit input
          ["slant2", "screen_db", "SlantTest.cfg"],
          ["slant3", "screen_db", "SlantTest.cfg"],
          ["slant4", "screen_db", "SlantTest.cfg"],
          ["slant4-cp", "screen_db", "SlantTest-sNB.cfg"]);

uni_test (++$testnumber, "CNB competition test",            # explicit input
          ["mihi", "mbb_143_db", "CnbCompTest.cfg"],
          ["mbbcrop", "mbb_143_db", "CnbCompTest.cfg"]);

uni_test (++$testnumber, "inline test",                     # explicit input
          ["hole1",      "manplab_db1", "InlineTestI.cfg"],
          ["hole1-cp",   "manplab_db1", "InlineTestI-sNB.cfg"],
          ["linespace1", "manplab_db2", "InlineTestI.cfg"], 
          ["linespace2", "manplab_db2", "InlineTestII.cfg"],
          ["linespace2-cp", "manplab_db2", "InlineTestII-sNB.cfg"],
          ["linespace3", "mbb_143_db", "InlineTestI.cfg"]);

uni_test (++$testnumber, "small pattern",                   # explicit input
          ["screen1",   "screen_db",  "SmallPatternII.cfg"],
          ["screen2",   "screen_db",  "SmallPatternII.cfg"],
          ["screen3",   "screen_db",  "SmallPatternII.cfg"],
          ["screen3-cp", "screen_db", "SmallPatternII-sNB.cfg"],
          ["screen4",   "screen_db4", "SmallPatternII.cfg"],
          ["screen5",   "screen_db",  "SmallPatternII.cfg"],
          ["screen5-cp", "screen_db", "SmallPatternII-sNB.cfg"],
          ["spanning1", "screen_db",  "SmallPatternII.cfg"],
          ["spanning2", "screen_db",  "SmallPatternII.cfg"],
          ["spanning3", "screen_db",  "SmallPatternII.cfg"],
          ["stroke1",   "screen_db",  "SmallPatternI.cfg"],
          ["stroke2",   "screen_db",  "SmallPatternI.cfg"],
          ["stroke3",   "screen_db",  "SmallPatternI.cfg"]);

pattern_matching1 ++$testnumber, @entry;                    # implicit input

uni_test (++$testnumber, "classification test II",          # explicit input
          ["doc_ex_1", "doc_ex_1_db", "ClassificationTest.cfg"]);

cluster_test (++$testnumber,	                             # explicit input
              ["ClusterTest1", "ClusterTest1_db"],
              ["ClusterTest2", "ClusterTest2_db"],
              ["ClusterTest3", "ClusterTest3_db"],
              ["plaball", "plaball_db"]);

uni_test (++$testnumber, "multiline RB test",                # explicit input
	  ["multiline3", "mbb_143_db", "MultilineRbTest.cfg"],
	  ["multiline2", "mbb_143_db", "MultilineRbTest.cfg"],
	  ["multiline1", "manplab_db2", "MultilineRbTest.cfg"]);

tiles_test (++$testnumber, "RB chains test",                 # explicit input
	  ["claraI.pgm", "mbb_143_db", "TilesTest.cfg"]);

uni_test (++$testnumber, "broken pattern test",              # explicit input
          ["broken1a1", "broken_db", "broken.cfg"],
          ["broken1a",  "broken_db", "broken.cfg"],
          ["broken1b",  "broken_db", "broken.cfg"],
          ["broken1c",  "broken_db", "broken.cfg"],
          ["broken1d",  "broken_db", "broken.cfg"],
          ["broken1e",  "broken_db", "broken.cfg"],
          ["broken1f",  "broken_db", "broken.cfg"],
          ["broken1g",  "broken_db", "broken.cfg"],
          ["broken1h",  "broken_db", "broken.cfg"],
          ["broken2",   "cbuch_db",  "ClassificationTest-b.cfg"],
          ["broken3",   "mnet_db",   "mnet.cfg"],
          ["peterson1",   "peter_db",   "peter.cfg"]);

exit if $opt_l;

time_diff "(Test Time ", ")\n", $start_test_time, time, 1;

sleep 2;
print STDERR "\a\n";
sleep 2;
print STDERR "\a\n";
sleep 2;
print STDERR "\a\n";

##############################################################################
sub print_test_header ($$) {
  my $testnumber = shift(@_);
  my $testname = shift(@_);

  print '=' x 79, "\n" if !$opt_l;
  print '=' x 68, "- XPLAB -==";
  print "\r========= $testname \r==[$testnumber]\n";
  print '=' x 79, "\n" if !$opt_l;
}
##############################################################################
sub time_diff ($$$$$) {
  my ($prefix, $suffix, $start, $end, $minutes, $seconds, $format_is_min);

  $prefix = shift(@_);
  $suffix = shift(@_);
  $start  = shift(@_);
  $end    = shift(@_);
  $format_is_min = shift(@_);

  $seconds = $end - $start;

  if ($format_is_min) {
    $minutes = int $seconds/60;
  }
  else {
    $minutes = 0;
  }

  $seconds -= $minutes*60;

  printf $prefix;
  printf "%dmin  ", $minutes if($minutes);
  printf "%dsec", $seconds;
  printf $suffix;
}
##############################################################################
sub cluster_test (@) {
  my $number = shift(@_);
  my @entry = @_;                                   # named formal argument
  my ($cpicref, $clsref, $rpttmp, $rptref, $cpictmp, $pass, $clstmp);
  my ($pic, $picref, $diff, $fail, $fail_sum, $warn, $warn_sum);
  my ($start_time, $start_runtime, $total);
  my ($line, $next, $command, $db, $dbin, $dbnewtmp, $dballtmp, $dbnewref);

  return if $single_test && $single_test != $number;
  print_test_header $number, "cluster test";
  return if $opt_l;

  $pass = 0;
  $total = 0;
  $fail_sum = 0;
  $warn_sum = 0;
  $start_runtime = time;

  foreach $line (@entry) {
    $pic = @$line[0];                           # input structure: testfile
    $db  = @$line[1];                           # input structure: database

    $dbin      = $db     . ".TC-IN";   
    $picref    = $pic    . ".TC-IN";            # picture under test
    $cpicref   = $pic    . ".cluster.TC-OUT";   
    $clsref    = $pic    . ".crf.TC-OUT";    
    $rptref    = $pic    . ".rpt.TC-OUT";    
    $dbnewref  = $db     . ".TC-OUT";
    $dbnewtmp  = $dbin   . ".new";   
    $dballtmp  = $dbin   . ".all";   
    $cpictmp   = $picref . ".cluster";
    $rpttmp    = $picref . ".rpt";    
    $clstmp    = $picref . ".crf";

    $fail = 0;
    $warn = 0;
    $next = 0;

    print "Testcase $pic ... ";

    if (!(-e $dbnewref && -f $dbnewref)) {             # available?
      print " $err_str\a\n" if !$next;
      print "$dbnewref missed\n";
      $next = 1;
    }

    if (!(-e $clsref && -f $clsref)) {                 # available?
      print " $err_str\a\n" if !$next;
      print "$clsref missed\n";
      $next = 1;
    }

    if (!(-e $rptref && -f $rptref)) {                 # available?
      print " $err_str\a\n" if !$next;
      print "$rptref missed\n";
      $next = 1;
    }

    if (!(-e $cpicref && -f $cpicref)) {               # available?
      print " $err_str\a\n" if !$next;
      print "$cpicref missed\n";
      $next = 1;
    }

    next if $next;

    $start_time = time;

    $command = "$xplab -Y -D $dbin -c ClusterTest.cfg $picref";
    `$command $cmd_ext`;
    $? == 0 || die "$command Died";                     # program stopped

    time_diff " (", ")  ", $start_time, time, 0;

    $diff = `diff $dbnewtmp $dbnewref 2>&1`;            # difference DB
    if ($diff) {
      print " $bad_str  [$command]\a\n";
      print "BEGIN [diff $dbnewtmp $dbnewref]\n";
      print $diff;
      print "END   [diff $dbnewtmp $dbnewref]\n";
      $fail = 1;
    }

    $diff = `diff $rpttmp $rptref 2>&1`;                # difference report
    if ($diff) {
      if (!$fail) {
        if ($opt_u) {
          `cp $rpttmp $rptref`;                # only overwrite if no fails
          print " $update_str\n" if !$warn;
        }
        else {
          print " $warn_str\n" if !$warn;
        }

        $warn = 1;
      }

      if (!$opt_u || $fail) {
        print "BEGIN [diff $rpttmp $rptref]\n";
        print $diff;
        print "END   [diff $rpttmp $rptref]\n";
      }
    }

    $diff = `diff $clstmp $clsref 2>&1`;         # difference generation
    if ($diff) {
      if (!$fail) {
        if ($opt_u) {
          `cp $clstmp $clsref`;                  # only overwrite if no fails
          print " $update_str\n" if !$warn;
        }
        else {
          print " $warn_str\n" if !$warn;
        }

        $warn = 1;
      }

      if (!$opt_u || $fail) {
        print "BEGIN [diff $clstmp $clsref]\n";
        print $diff;
        print "END   [diff $clstmp $clsref]\n";
      }
    }

    $diff = `diff $cpictmp $cpicref 2>&1`;       # difference cluster picture
    if ($diff) {
      if (!$fail) {
        if ($opt_u) {
          `cp $cpictmp $cpicref`;                # only overwrite if no fails
          print " $update_str\n" if !$warn;
        }
        else {
          print " $warn_str\n" if !$warn;
        }

        $warn = 1;
      }

      if ($warn || $fail) {
        print "BEGIN [diff $cpictmp $cpicref]\n";
        print $diff;
        print "END   [diff $cpictmp $cpicref]\n";
      }
    }

    $fail_sum++ if $fail;
    $warn_sum++ if $warn;

    print " $good_str\n" if (!$fail && !$warn);
    print '=' x 79, "\n" if ($fail || ($warn && !$opt_u));

    $total++;

    if (!$fail && !$warn && !$opt_k) {            # remove temporary file
      `rm $dballtmp 2>&1`;
      `rm $dbnewtmp 2>&1`;
      `rm $rpttmp 2>&1`;
      `rm $clstmp 2>&1`;   
      `rm $cpictmp 2>&1`;
    }
  }

  $pass = $total-$fail_sum-$warn_sum;

  print "\n $good_str $pass";                          # output statistic
  print "\n $bad_str $fail_sum";
  print "\n $update_str $warn_sum" if $opt_u;
  print "\n $warn_str $warn_sum" if !$opt_u;
  print "\n$sum_str $total  ";
  time_diff "(runtime ", ")\n\n", $start_runtime, time, 1;
}
##############################################################################
sub chain_test (@) {
  my $number = shift(@_);
  my @entry = @_;                                   # named formal argument
  my ($pic, $picref, $diff, $fail, $fail_sum, $warn, $warn_sum, $next);
  my ($start_time, $start_runtime, $total);
  my ($txttmp, $txtref, $rpttmp, $rptref, $command, $pass, $dbin);

  return if $single_test && $single_test != $number;
  print_test_header $number, "concatenation test";
  return if $opt_l;

  $pass = 0;
  $total = 0;
  $fail_sum = 0;
  $warn_sum = 0;
  $start_runtime = time;

  $dbin = "ChainTest_db.TC-IN";

  foreach $picref (@entry) {
    next if ($picref !~ /^ChainTest+.TC-IN$/);         # not a test file

    ($pic = $picref) =~ s/.TC-IN//;                    # picture under test
    $txtref = $pic . ".txt.TC-OUT";                    # text
    $rptref = $pic . ".rpt.TC-OUT";                    # report
    $rpttmp = $picref . ".rpt";                        # report
    $txttmp = $picref . ".txt";

    $fail = 0;
    $warn = 0;
    $next = 0;

    print "Testcase $pic ... ";

    if (!(-e $txtref && -f $txtref)) {                 # available?
      print " $err_str\a\n" if !$next;
      print "$txtref missed\n";
      $next = 1;
    }

    if (!(-e $rptref && -f $rptref)) {                 # available?
      print " $err_str\a\n" if !$next;
      print "$rptref missed\n";
      $next = 1;
    }

    next if $next;

    $start_time = time;

    $command = "$xplab -Y -D $dbin -c ChainTest.cfg $picref";
    `$command $cmd_ext`;
    $? == 0 || die "$command Died";                    # program stopped

    time_diff " (", ")  ", $start_time, time, 0;

    $diff = `diff $txttmp $txtref 2>&1`;               # difference text
    if ($diff) {
      print " $bad_str  [$command]\a\n";
      print "BEGIN [diff $txttmp $txtref]\n";
      print $diff;
      print "END   [diff $txttmp $txtref]\n";
      $fail = 1;
      }

    $diff = `diff $rpttmp $rptref 2>&1`;              # difference report
    if ($diff) {
      if (!$fail) {
        if ($opt_u) {
          `cp $rpttmp $rptref`;       # overwrite reports only if no fails
          print " $update_str\n" if !$warn;
        }
        else {
          print " $warn_str\n" if !$warn;
        }

        $warn = 1;
      }

      if (!$opt_u || $fail) {
        print "BEGIN [diff $rpttmp $rptref]\n";
        print $diff;
        print "END   [diff $rpttmp $rptref]\n";
      }
    }

    $fail_sum++ if $fail;
    $warn_sum++ if $warn;

    print " $good_str\n" if (!$fail && !$warn);
    print '=' x 79, "\n" if ($fail || ($warn && !$opt_u));

    $total++;

    if (!$fail && !$warn && !$opt_k) {            # remove temporary file
      `rm $txttmp 2>&1`;   
      `rm $rpttmp 2>&1`;
    }
  }

  $pass = $total-$fail_sum-$warn_sum;

  print "\n $good_str $pass";                          # output statistic
  print "\n $bad_str $fail_sum";
  print "\n $update_str $warn_sum" if $opt_u;
  print "\n $warn_str $warn_sum" if !$opt_u;
  print "\n$sum_str $total  ";
  time_diff "(runtime ", ")\n\n", $start_runtime, time, 1;
}
##############################################################################
sub connect_test (@) {
  my $number = shift(@_);
  my @entry = @_;                                   # named formal argument
  my ($pic, $picref, $diff, $fail, $fail_sum, $pass, $warn, $warn_sum, $next);
  my ($start_time, $start_runtime, $total);
  my ($txttmp, $txtref, $rpttmp, $rptref, $command, $dbin);

  return if $single_test && $single_test != $number;
  print_test_header $number, "connect test";
  return if $opt_l;

  $pass = 0;
  $total = 0;
  $fail_sum = 0;
  $warn_sum = 0;
  $start_runtime = time;

  $dbin = "ConnectTest_db.TC-IN";

  foreach $picref (@entry) {
    next if ($picref !~ /^ConnectTest+.TC-IN$/);       # not a test file

    ($pic = $picref) =~ s/.TC-IN//;                    # picture under test
    $txtref = $pic . ".txt.TC-OUT";                    # text
    $rptref = $pic . ".rpt.TC-OUT";                    # report
    $rpttmp = $picref . ".rpt";                        # report
    $txttmp = $picref . ".txt";

    $fail = 0;
    $warn = 0;
    $next = 0;

    print "Testcase $pic ... ";

    if (!(-e $txtref && -f $txtref)) {                 # available?
      print " $err_str\a\n" if !$next;
      print "$txtref missed\n";
      $next = 1;
    }

    if (!(-e $rptref && -f $rptref)) {                 # available?
      print " $err_str\a\n" if !$next;
      print "$rptref missed\n";
      $next = 1;
    }

    next if $next;

    $start_time = time;

    $command = "$xplab -Y -D $dbin -c ConnectTest.cfg $picref";
    `$command $cmd_ext`;
    $? == 0 || die "$command Died";                    # program stopped

    time_diff " (", ")  ", $start_time, time, 0;

    $diff = `diff $txttmp $txtref 2>&1`;               # difference text
    if ($diff) {
      print " $bad_str  [$command]\a\n";
      print "BEGIN [diff $txttmp $txtref]\n";
      print $diff;
      print "END   [diff $txttmp $txtref]\n";
      $fail = 1;
    }

    $diff = `diff $rpttmp $rptref 2>&1`;               # difference report
    if ($diff) {
      if (!$fail) {
        if ($opt_u) {
          `cp $rpttmp $rptref`;               # only overwrite if no fails
          print " $update_str\n" if !$warn;
        }
        else {
          print " $warn_str\n" if !$warn;
        }

        $warn = 1;
      }

      if (!$opt_u || $fail) {
        print "BEGIN [diff $rpttmp $rptref]\n";
        print $diff;
        print "END   [diff $rpttmp $rptref]\n";
      }
    }

    $fail_sum++ if $fail;
    $warn_sum++ if $warn;

    print " $good_str\n" if (!$fail && !$warn);
    print '=' x 79, "\n" if ($fail || ($warn && !$opt_u));

    $total++;

    if (!$fail && !$warn && !$opt_k) {            # remove temporary file
      `rm $txttmp 2>&1`;   
      `rm $rpttmp 2>&1`;
    }
  }

  $pass = $total-$fail_sum-$warn_sum;

  print "\n $good_str $pass";                          # output statistic
  print "\n $bad_str $fail_sum";
  print "\n $update_str $warn_sum" if $opt_u;
  print "\n $warn_str $warn_sum" if !$opt_u;
  print "\n$sum_str $total  ";
  time_diff "(runtime ", ")\n\n", $start_runtime, time, 1;
}
##############################################################################
sub sequence_test (@) {
  my $number = shift(@_);
  my @entry = @_;                                   # named formal argument
  my ($pic, $picref, $diff, $fail, $fail_sum, $pass, $warn, $warn_sum, $next);
  my ($start_time, $start_runtime, $total);
  my ($txttmp, $txtref, $rpttmp, $rptref, $command, $dbin);

  return if $single_test && $single_test != $number;
  print_test_header $number, "sequence test";
  return if $opt_l;

  $pass = 0;
  $total = 0;
  $fail_sum = 0;
  $warn_sum = 0;
  $start_runtime = time;

  $dbin = "SequenceTest_db.TC-IN";

  foreach $picref (@entry) {
    next if ($picref !~ /^SequenceTest\d+.TC-IN$/);    # no result file

    ($pic = $picref) =~ s/.TC-IN//;                    # picture under test
    $txtref = $pic . ".txt.TC-OUT";                    # text
    $rptref = $pic . ".rpt.TC-OUT";                    # report
    $rpttmp = $picref . ".rpt";                        # report
    $txttmp = $picref . ".txt";

    $fail = 0;
    $warn = 0;
    $next = 0;

    print "Testcase $pic ... ";

    if (!(-e $txtref && -f $txtref)) {                 # only if available
      print " $err_str\a\n" if !$next;
      print "$txtref missed\n";
      $next = 1;
    }

    if (!(-e $rptref && -f $rptref)) {                 # only if available
      print " $err_str\a\n" if !$next;
      print "$rptref missed\n";
      $next = 1;
    }

    next if $next;

    $start_time = time;

    $command = "$xplab -Y -D $dbin -c SequenceTest.cfg $picref";
    `$command $cmd_ext`;
    $? == 0 || die "$command Died";                    # program stopped

    time_diff " (", ")  ", $start_time, time, 0;

    $diff = `diff $txttmp $txtref 2>&1`;              # difference text
    if ($diff) {
      print " $bad_str  [$command]\a\n";
      print "BEGIN [diff $txttmp $txtref]\n";
      print $diff;
      print "END   [diff $txttmp $txtref]\n";
      $fail = 1;
    }

    $diff = `diff $rpttmp $rptref 2>&1`;               # difference report
    if ($diff) {
      if (!$fail) {
        if ($opt_u) {
          `cp $rpttmp $rptref`;               # only overwrite if no fails
          print " $update_str\n" if !$warn;
        }
        else {
          print " $warn_str\n" if !$warn;
        }

        $warn = 1;
      }

      if (!$opt_u || $fail) {
        print "BEGIN [diff $rpttmp $rptref]\n";
        print $diff;
        print "END   [diff $rpttmp $rptref]\n";
      }
    }

    $fail_sum++ if $fail;
    $warn_sum++ if $warn;

    print " $good_str\n" if (!$fail && !$warn);
    print '=' x 79, "\n" if ($fail || ($warn && !$opt_u));

    $total++;

    if (!$fail && !$warn && !$opt_k) {            # remove temporary file
      `rm $txttmp 2>&1`;   
      `rm $rpttmp 2>&1`;
    }
  }

  $pass = $total-$fail_sum-$warn_sum;

  print "\n $good_str $pass";                          # output statistic
  print "\n $bad_str $fail_sum";
  print "\n $update_str $warn_sum" if $opt_u;
  print "\n $warn_str $warn_sum" if !$opt_u;
  print "\n$sum_str $total  ";
  time_diff "(runtime ", ")\n\n", $start_runtime, time, 1;
}
##############################################################################
sub separation_test (@) {
  my $number = shift(@_);
  my @entry = @_;                                   # named formal argument
  my ($pic, $picref, $diff, $fail, $fail_sum, $pass, $warn, $warn_sum, $next);
  my ($start_time, $start_runtime, $total);
  my ($txttmp, $txtref, $dbin, $rpttmp, $rptref, $command);

  return if $single_test && $single_test != $number;
  print_test_header $number, "separation test";
  return if $opt_l;

  $pass = 0;
  $total = 0;
  $fail_sum = 0;
  $warn_sum = 0;
  $start_runtime = time;

  $dbin = "SequenceTest_db.TC-IN";

  foreach $picref (@entry) {
    next if ($picref !~ /^SeparationTest\d+.TC-IN$/);  # no result file

    ($pic = $picref) =~ s/.TC-IN//;                    # picture under test
    $txtref = $pic . ".txt.TC-OUT";                    # text
    $rptref = $pic . ".rpt.TC-OUT";                    # report
    $rpttmp = $picref . ".rpt";                        # report
    $txttmp = $picref . ".txt";

    $fail = 0;
    $warn = 0;
    $next = 0;

    print "Testcase $pic ... ";

    if (!(-e $txtref && -f $txtref)) {                 # only if available
      print " $err_str\a\n" if !$next;
      print "$txtref missed\n";
      $next = 1;
    }

    if (!(-e $rptref && -f $rptref)) {                 # only if available
      print " $err_str\a\n" if !$next;
      print "$rptref missed\n";
      $next = 1;
    }

    next if $next;

    $start_time = time;

    $command = "$xplab -Y -D $dbin -c SeparationTest.cfg $picref";
    `$command $cmd_ext`;
    $? == 0 || die "$command Died";                    # program stopped

    time_diff " (", ")  ", $start_time, time, 0;

    $diff = `diff $txttmp $txtref 2>&1`;               # difference text
    if ($diff) {
      print " $bad_str  [$command]\a\n";
      print "BEGIN [diff $txttmp $txtref]\n";
      print $diff;
      print "END   [diff $txttmp $txtref]\n";
      $fail = 1;
    }

    $diff = `diff $rpttmp $rptref 2>&1`;               # difference report
    if ($diff) {
      if (!$fail) {
        if ($opt_u) {
          `cp $rpttmp $rptref`;               # only overwrite if no fails
          print " $update_str\n" if !$warn;
        }
        else {
          print " $warn_str\n" if !$warn;
        }

        $warn = 1;
      }

      if (!$opt_u || $fail) {
        print "BEGIN [diff $rpttmp $rptref]\n";
        print $diff;
        print "END   [diff $rpttmp $rptref]\n";
      }
    }

    $fail_sum++ if $fail;
    $warn_sum++ if $warn;

    print " $good_str\n" if (!$fail && !$warn);
    print '=' x 79, "\n" if ($fail || ($warn && !$opt_u));

    $total++;

    if (!$fail && !$warn && !$opt_k) {            # remove temporary file
      `rm $txttmp 2>&1`;   
      `rm $rpttmp 2>&1`;
    }
  }

  $pass = $total-$fail_sum-$warn_sum;

  print "\n $good_str $pass";                          # output statistic
  print "\n $bad_str $fail_sum";
  print "\n $update_str $warn_sum" if $opt_u;
  print "\n $warn_str $warn_sum" if !$opt_u;
  print "\n$sum_str $total  ";
  time_diff "(runtime ", ")\n\n", $start_runtime, time, 1;
}
##############################################################################
sub single_dot_test (@) {
  my $number = shift(@_);
  my @entry = @_;                                   # named formal argument
  my @ext = (".DC.2D.b",          # XPLAB's file extension: bitmapped input
             ".DC.2D.c");         # XPLAB's file extension: clean picture used
  my ($picref, $tst, $pictmp, $pic, $diff, $fail_sum, $fail, $pass, $next);
  my ($start_time, $start_runtime, $total, $picin);
  my ($command);

  return if $single_test && $single_test != $number;
  print_test_header $number, "single dot test";
  return if $opt_l;

  $pass = 0;
  $total = 0;
  $fail_sum = 0;
  $start_runtime = time;

  foreach $picin (@entry) {
    next if ($picin !~ /^SingleTest\d+.TC-IN$/);       # not a test file

    ($pic = $picin) =~ s/.TC-IN//;                     # picture under test

    $fail = 0;
    $next = 0;

    print "Testcase $pic ... ";

    foreach $tst (@ext) {
      $pictmp = $picin . $tst;
      $picref = $pic . $tst . ".TC-OUT";

      if (!(-e $picref && -f $picref)) {               # available?
        print " $err_str\a\n" if !$next;
        print "$picref missed\n";
        $next = 1;
        next;
      }
    }

    next if $next;                      # all test results must be available

    $start_time = time;

    $command = "$xplab -Y -c SingleTest.cfg $picin";
    `$command $cmd_ext`;
    $? == 0 || die "$command Died";                    # program stopped

    time_diff " (", ")  ", $start_time, time, 0;
  
    foreach $tst (@ext) {
      $pictmp = $picin . $tst;
      $picref = $pic . $tst . ".TC-OUT";

      $diff = `diff $pictmp $picref 2>&1`;             # check difference
      if ($diff) {
        print " $bad_str  [$command]\a\n";
        print "BEGIN [diff $pictmp $picref]\n";
        print $diff;
        print "END   [diff $pictmp $picref]\n";
        $fail = 1;
      }
    }

    $fail_sum++ if $fail;

    print " $good_str\n" if (!$fail);
    print '=' x 79, "\n" if ($fail);

    $total++;

    if (!$fail && !$opt_k) {                      # remove temporary file
      foreach $tst (@ext) {
        $pictmp = $picin . $tst;
        `rm $pictmp 2>&1`;
      }
    }
  }

  $pass = $total-$fail_sum;

  print "\n $good_str $pass";                          # output statistic
  print "\n $bad_str $fail_sum";
  print "\n$sum_str $total  ";
  time_diff "(runtime ", ")\n\n", $start_runtime, time, 1;
}

##############################################################################
sub pattern_matching1 (@) {
  my $number = shift(@_);
  my @entry = @_;                                   # named formal argument
  my ($pic, $picref, $diff, $fail, $fail_sum, $pass, $warn, $warn_sum, $next);
  my ($start_time, $start_runtime, $total);
  my ($txttmp, $txtref, $rpttmp, $rptref, $command, $dbref);

  return if $single_test && $single_test != $number;
  print_test_header $number, "classification test I";
  return if $opt_l;

  $pass = 0;
  $total = 0;
  $fail_sum = 0;
  $warn_sum = 0;
  $start_runtime = time;

  foreach $picref (@entry) {
    next if ($picref !~ /^crop\d+[a-zA-Z]*.TC-IN$/);   # not a test file

    ($pic = $picref) =~ s/.TC-IN//;                    # picture under test
    $dbref  = "cbuch_db.TC-IN";                        # used DB
    $txtref = $pic . ".txt.TC-OUT";                    # text
    $rptref = $pic . ".rpt.TC-OUT";                    # report
    $rpttmp = $picref . ".rpt";                        # report
    $txttmp = $picref . ".txt";

    $fail = 0;
    $warn = 0;
    $next = 0;

    print "Testcase $pic ... ";

    if (!(-e $txtref && -f $txtref)) {                 # available?
      print " $err_str\a\n" if !$next;
      print "$txtref missed\n";
      $next = 1;
    }

    if (!(-e $rptref && -f $rptref)) {                 # available?
      print " $err_str\a\n" if !$next;
      print "$rptref missed\n";
      $next = 1;
    }

    next if $next;

    $start_time = time;

    $command = "$xplab -Y -D $dbref -c ClassificationTest.cfg $picref";
    `$command $cmd_ext`;
    $? == 0 || die "$command Died";                    # program stopped

    time_diff " (", ")  ", $start_time, time, 0;

    $diff = `diff $txttmp $txtref 2>&1`;               # difference text
    if ($diff) {
      print " $bad_str  [$command]\a\n";
      print "BEGIN [diff $txttmp $txtref]\n";
      print $diff;
      print "END   [diff $txttmp $txtref]\n";
      $fail = 1;
    }

    $diff = `diff $rpttmp $rptref 2>&1`;               # difference report
    if ($diff) {
      if (!$fail) {
        if ($opt_u) {
          `cp $rpttmp $rptref`;               # only overwrite if no fails
          print " $update_str\n" if !$warn;
        }
        else {
          print " $warn_str\n" if !$warn;
        }

        $warn = 1;
      }

      if (!$opt_u || $fail) {
        print "BEGIN [diff $rpttmp $rptref]\n";
        print $diff;
        print "END   [diff $rpttmp $rptref]\n";
      }
    }

    $fail_sum++ if $fail;
    $warn_sum++ if $warn;

    print " $good_str\n" if (!$fail && !$warn);
    print '=' x 79, "\n" if ($fail || ($warn && !$opt_u));

    $total++;

    if (!$fail && !$warn && !$opt_k) {            # remove temporary file
      `rm $txttmp 2>&1`;   
      `rm $rpttmp 2>&1`;
    }
  }

  $pass = $total-$fail_sum-$warn_sum;

  print "\n $good_str $pass";                          # output statistic
  print "\n $bad_str $fail_sum";
  print "\n $update_str $warn_sum" if $opt_u;
  print "\n $warn_str $warn_sum" if !$opt_u;
  print "\n$sum_str $total  ";
  time_diff "(runtime ", ")\n\n", $start_runtime, time, 1;
}

##############################################################################
sub uni_test (@) {
  my $number = shift(@_);
  my $test_name = shift(@_);
  my @entry = @_;                                   # named formal argument
  my ($txtref, $pic, $diff, $fail, $fail_sum, $pass, $warn, $warn_sum);
  my ($start_time, $start_runtime, $total, $picref);
  my ($line, $next, $command, $db, $dbin, $rptref, $txttmp, $rpttmp, $xcfg);

  return if $single_test && $single_test != $number;
  print_test_header $number, $test_name;
  return if $opt_l;

  $pass = 0;
  $total = 0;
  $fail_sum = 0;
  $warn_sum = 0;
  $start_runtime = time;

  foreach $line (@entry) {
    $pic  = @$line[0];                          # input structure: testfile
    $db   = @$line[1];                          # input structure: database
    $xcfg = @$line[2];                          # input structure: config

    $dbin   = $db  . ".TC-IN";   
    $picref = $pic . ".TC-IN";                  # picture under test
    $txtref = $pic . ".txt.TC-OUT";             # text
    $rptref = $pic . ".rpt.TC-OUT";             # report
    $rpttmp = $picref . ".rpt";                 # report
    $txttmp = $picref . ".txt";

    $fail = 0;
    $warn = 0;
    $next = 0;

    print "Testcase $pic ... ";

    if (!(-e $picref && -f $picref)) {                 # available?
      print " $err_str\a\n" if !$next;
      print "$picref missed\n";
      $next = 1;
    }

    if (!(-e $txtref && -f $txtref)) {                 # available?
      print " $err_str\a\n" if !$next;
      print "$txtref missed\n";
      $next = 1;
    }

    if (!(-e $rptref && -f $rptref)) {                 # available?
      print " $err_str\a\n" if !$next;
      print "$rptref missed\n";
      $next = 1;
    }

    if (!(-e $xcfg && -f $xcfg)) {                     # available?
      print " $err_str\a\n" if !$next;
      print "$xcfg missed\n";
      $next = 1;
    }

    next if $next;

    $start_time = time;

    $command = "$xplab -Y -D $dbin -c $xcfg $picref";
    `$command $cmd_ext`;
    $? == 0 || die "$command Died";                    # program stopped

    time_diff " (", ")  ", $start_time, time, 0;

    $diff = `diff $txttmp $txtref 2>&1`;               # difference text
    if ($diff) {
      print " $bad_str  [$command]\a\n";
      print "BEGIN [diff $txttmp $txtref]\n";
      print $diff;
      print "END   [diff $txttmp $txtref]\n";
      $fail = 1;
    }

    $diff = `diff $rpttmp $rptref 2>&1`;               # difference report
    if ($diff) {
      if (!$fail) {
        if ($opt_u) {
          `cp $rpttmp $rptref`;               # only overwrite if no fails
          print " $update_str\n" if !$warn;
        }
        else {
          print " $warn_str\n" if !$warn;
        }

        $warn = 1;
      }

      if (!$opt_u || $fail) {
        print "BEGIN [diff $rpttmp $rptref]\n";
        print $diff;
        print "END   [diff $rpttmp $rptref]\n";
      }
    }

    $fail_sum++ if $fail;
    $warn_sum++ if $warn;

    print " $good_str\n" if (!$fail && !$warn);
    print '=' x 79, "\n" if ($fail || ($warn && !$opt_u));

    $total++;

    if (!$fail && !$warn && !$opt_k) {            # remove temporary file
      `rm $txttmp 2>&1`;   
      `rm $rpttmp 2>&1`;
    }
  }

  $pass = $total-$fail_sum-$warn_sum;

  print "\n $good_str $pass";                          # output statistic
  print "\n $bad_str $fail_sum";
  print "\n $update_str $warn_sum" if $opt_u;
  print "\n $warn_str $warn_sum" if !$opt_u;
  print "\n$sum_str $total  ";
  time_diff "(runtime ", ")\n\n", $start_runtime, time, 1;
}

##############################################################################
sub tiles_test (@) {
  my $number = shift(@_);
  my $test_name = shift(@_);
  my @entry = @_;                                   # named formal argument
  my ($pic, $diff, $fail, $fail_sum, $pass, $warn, $warn_sum);
  my ($start_time, $start_runtime, $total, $picref, $tiltmp, $tilref);
  my ($line, $next, $command, $db, $dbin, $rptref, $rpttmp, $xcfg);
  my ($til, @reflist, $refcnt, @tmplist, $tmpcnt, $colref, $coltmp);

  return if $single_test && $single_test != $number;
  print_test_header $number, $test_name;
  return if $opt_l;

  $pass = 0;
  $total = 0;
  $fail_sum = 0;
  $warn_sum = 0;
  $start_runtime = time;

  foreach $line (@entry) {
    $pic  = @$line[0];                          # input structure: testfile
    $db   = @$line[1];                          # input structure: database
    $xcfg = @$line[2];                          # input structure: config

    $dbin   = $db  . ".TC-IN";   
    $picref = $pic . ".TC-IN";                  # picture under test
    $rptref = $pic . ".rpt.TC-OUT";             # report
    $rpttmp = $picref . ".rpt";                 # report

    $colref = $pic . ".tile.col.TC-OUT";        # colored tiles reference
    $coltmp = $picref . ".tile.col";                         # colored tiles 
    $tilref = $pic . ".tile.[0-9].TC-OUT";      # image tiles references
    chop($til = `ls $tilref $cmd_ext`);
    @reflist = split /^/m, $til;
    $refcnt = scalar(@reflist);

    $fail = 0;
    $warn = 0;
    $next = 0;

    print "Testcase $pic ... ";

    if (!(-e $picref && -f $picref)) {             # image source available?
      print " $err_str\a\n" if !$next;
      print "$picref missed\n";
      $next = 1;
    }

    if (!(-e $rptref && -f $rptref)) {         # report reference available?
      print " $err_str\a\n" if !$next;
      print "$rptref missed\n";
      $next = 1;
    }

    next if $next;

    $til =    $picref . ".tile.[0-9]";                            # clean up 
    `rm $til $cmd_ext`;                                       # single tiles
    $til =    $picref . ".tile.col";
    `rm $til $cmd_ext`;                                      # colored tiles

    $start_time = time;

    $command = "$xplab -Y -D $dbin -c $xcfg $picref";
    `$command $cmd_ext`;
    $? == 0 || die "$command Died";                        # program stopped

    time_diff " (", ")  ", $start_time, time, 0;

    $tiltmp = $picref . ".tile.[0-9]";                  # single image tiles 
    chop($til = `ls $tiltmp $cmd_ext`);
    @tmplist = split /^/m, $til;
    $tmpcnt = scalar(@tmplist);

    if ($refcnt != $tmpcnt) {                        # different tile number
      print " $bad_str  [$command]\a\n";
      print "$err_str different tile number: found: $tmpcnt  expected: $refcnt\n";
      $fail = 1;
    }

    while ($tmpcnt--) {
      $tilref = $pic . ".tile.$tmpcnt.TC-OUT";      # image tile reference
      $tiltmp = $picref . ".tile.$tmpcnt";                 # image tile 

      if (!(-e $tilref && -f $tilref)) {    # image tile reference available?
        print "$err_str $tilref missed\n";
        $fail = 1;
      }
      else {
        $diff = `diff $tiltmp $tilref 2>&1`;               # difference tiles

        if ($diff) {
          print " $bad_str  [$command]\a\n";
          print "BEGIN [diff $tiltmp $tilref]\n";
          print $diff;
          print "END   [diff $tiltmp $tilref]\n";
          $fail = 1;
        }
      }
    }

    if (-e $coltmp && -f $coltmp) {                # colored tiles available?
      if (-e $colref && -f $colref) {     # colored tile reference available?
        $diff = `diff $coltmp $colref 2>&1`;               # difference tiles

        if ($diff) {
          print " $bad_str  [$command]\a\n";
          print "BEGIN [diff $coltmp $colref]\n";
          print $diff;
          print "END   [diff $coltmp $colref]\n";
          $fail = 1;
	}
      }
      else {
        print "$err_str $colref missed\n";
        $fail = 1;
      }
    }
    else {
      if (-e $colref && -f $colref) {     # colored tile reference available?
        print " $bad_str  [$command]\a\n";
        print "$err_str $coltmp missed\n";
        $fail = 1;
      }
    }

    $diff = `diff $rpttmp $rptref 2>&1`;                 # difference report
    if ($diff) {
      if (!$fail) {
        if ($opt_u) {
          `cp $rpttmp $rptref`;                 # only overwrite if no fails
          print " $update_str\n" if !$warn;
        }
        else {
          print " $warn_str\n" if !$warn;
        }

        $warn = 1;
      }

      if (!$opt_u || $fail) {
        print "BEGIN [diff $rpttmp $rptref]\n";
        print $diff;
        print "END   [diff $rpttmp $rptref]\n";
      }
    }

    $fail_sum++ if $fail;
    $warn_sum++ if $warn;

    print " $good_str\n" if (!$fail && !$warn);
    print '=' x 79, "\n" if ($fail || ($warn && !$opt_u));

    $total++;

    if (!$fail && !$warn && !$opt_k) {            # remove temporary file
      `rm $rpttmp $cmd_ext`;
      `rm $coltmp $cmd_ext`;

      $tmpcnt = scalar(@tmplist);

      while ($tmpcnt--) {
        $tiltmp = $picref . ".tile.$tmpcnt";                    # image tile 
        `rm $tiltmp $cmd_ext`;
      }
    }
  }

  $pass = $total-$fail_sum-$warn_sum;

  print "\n $good_str $pass";                          # output statistic
  print "\n $bad_str $fail_sum";
  print "\n $update_str $warn_sum" if $opt_u;
  print "\n $warn_str $warn_sum" if !$opt_u;
  print "\n$sum_str $total  ";
  time_diff "(runtime ", ")\n\n", $start_runtime, time, 1;
}

##############################################################################
