#!/bin/sh
# Vaucanson, a generic library for finite state machines.
# Copyright (C) 2001, 2002, 2004, 2005, 2006, 2008, 2011 The Vaucanson Group.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# The complete GNU General Public Licence Notice can be found as the
# `COPYING' file in the root directory.
#
# The Vaucanson Group consists of people listed in the `AUTHORS' file.

# Where the test include files are located from here.
test_include_root=../include
top_srcdir=../../..
build_auxdir=$top_srcdir/build-aux

# FIXME: For the time being disable the use of move-if-change because it
# leads to quadratic behavior...
#
# The generated Makefiles now include regeneration rules, but they are
# too coarse: they regenerate *all* the test-suite instead of just the
# one that needs to be updated.  But since we were using
# move-if-change, the Makefile were not updated, and we were going
# into an endless chain of (do-nothing) updates.
#
# In the future, we should use a timestamp system (as is done for
# config.h), and provide smarter means to *update* parts of the test
# suite, as opposed to regnerating the whole lot.


move_if_change=mv #$build_auxdir/move-if-change

# Don't ignore errors.
set -e

# Check args
if [ $# -le 2 ]; then
  echo 'usage: '
  echo "$0 destination_directory description_file tests_dirs"
  exit 1
fi

dest_dir=$1
description_file=$2
shift 2
test_dirs=$@


# dump_header COMMENT-PREFIX
# --------------------------
# Dump the part signaling a file is generated.
dump_header ()
{
    sed -e "s,^,$1 ,;s/  *$//" << EOF

DO NOT EDIT BY HAND - Generated by $0

Vaucanson, a generic library for finite state machines.
Copyright (C) 2001, 2002, 2004, 2005, 2006 The Vaucanson Group.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

The complete GNU General Public Licence Notice can be found as the
\`COPYING' file in the root directory.

The Vaucanson Group consists of people listed in the \`AUTHORS' file.

EOF
}

# find_tests SUFFIX DIRS...
# -------------------------
# Find all the tests/includes/tests/(DIRS/*_SUFFIX.hh).  Return the
# part in parens.
find_tests ()
{
  local suffix=$1
  shift
  (
      cd $test_include_root
      for d
      do
	find $d -name \*_$suffix.hh -not -name '*#*'
      done
  )
}


# Verbose mode
if [ -n "$VERBOSE" ]; then
  cat << EOF
* Arguments are:
 test directories        : $test_dirs
 destination directories : $dest_dir
 description files       : $description_file
EOF
fi

# if $dest_dir does not exists
if [ ! -d $dest_dir ]; then
    mkdir $dest_dir
fi

# Get all _test.hh
all_test=$(find_tests test $test_dirs)
all_failcomp=$(find_tests failcomp $test_dirs)

# For each header file in $1, this function generates a corresponding .cc
# file which includes a license, the .defs definitions, the test
# header file, and a main() function.
#
# All the header files in $1 must end with a common suffix given as $2.
#
# This function also prints a space separated list of all the
# generated .cc files, without the extension.
generate_CCs()
{
  local tests="$1"
  local suffix="$2"

  # Generate corresponding .cc
  for name in $tests
  do
    fun_name=$(basename $name .hh)
    fun_sname=$(echo $fun_name | sed "s/_$suffix//")
    name_test_file=$name

    # The file to create.
    local test_file_cc=$dest_dir/$fun_sname-$suffix.cc
    # Its tmp version which we move-if-change.
    local tmp_cc=$test_file_cc.tmp

    # Include licence.
    dump_header "//" >"$tmp_cc"

    # Include necessary Vaucanson headers.
    cat >> "$tmp_cc" <<EOF
#undef NDEBUG
#undef VCSN_NDEBUG
#include <cassert>
#include <vaucanson/design_pattern/design_pattern.hh>
#define CREATE_SEMIRING(m)

EOF

    # Include "main".
    cat >> "$tmp_cc" <<EOF
#include <$description_file>
#include <tests/check/tester.hh>
#include <$name_test_file>

int main(int argc, char **argv)
{
  using namespace vcsn;
  tests::Tester t(argc, argv);
  if ($fun_name<TEST_STATIC_ARGS>(t))
    return EXIT_SUCCESS;
  else
    return EXIT_FAILURE;
}
EOF

    # Save cycles by not regenerating files that did not change.
    $move_if_change "$tmp_cc" "$test_file_cc"

    echo "$fun_sname-$suffix"
  done | sort
}

check_programs=$(generate_CCs "$all_test" test)
failcomp_prog=$(generate_CCs "$all_failcomp" failcomp)

# Define the include directories.
for test_dir in $test_dirs
do
# FIXME: Of  course, this  does not work  in general case.
# FIXME: We must find a way to define  the path from dest_dir to test_dir
# FIXME: or to force  people to define an absolute  test_dir.
# FIXME: for the distributed tests suites, it works
    includes="-I\$(srcdir)/../$test_dir $includes"
done

#
# Generates the script to check failed compilations.
#
failcomp_script=$dest_dir/failcomp.sh
cat > $failcomp_script << \EOF
#! /bin/sh
EOF

dump_header "#" >>$failcomp_script
cat >> $failcomp_script << \EOF
fail ()
{
  echo "FAIL: Program $1 succeed to compile."
  exit 1
}

EOF

for prog in $failcomp_prog; do
  cat >> $failcomp_script << EOF
cmd="\$CXX \$CXXFLAGS -c \$srcdir/$prog.cc"
echo "*** THIS COMPILATION IS EXPECTED TO FAIL, THIS IS NOT A BUG ***"
echo \$cmd
\$cmd && fail $prog
echo "*** END OF FAILED COMPILATION, THIS IS NOT A BUG ***"

EOF
done

echo "exit 0" >> $failcomp_script
chmod 755 $failcomp_script


#
# Generate a Makefile.am
#
makefile=$dest_dir/Makefile.am
makefile_tmp=$makefile.tmp
{
    dump_header '##'
    cat << EOF
include \$(top_srcdir)/src/tests/test-suites/test-suite.mk

EXTRA_PROGRAMS =$(for i in $check_programs; do printf ' \\\n'"$i"; done)

EOF

    for prog in $check_programs
      do
      prog_canon=$(echo $prog | sed s/-/_/g)
      echo "${prog_canon}_SOURCES = $prog.cc"
    done
} > $makefile_tmp

$move_if_change $makefile_tmp $makefile
