#!/usr/bin/env python
#
# Copyright (C) 2005-2009 ABINIT Group (Yann Pouillon)
# All rights reserved.
#
# This file is part of the ABINIT software package. For license information,
# please see the COPYING file in the top-level directory of the ABINIT source
# distribution.
#

from time import gmtime,strftime

import commands
import os
import re
import sys

# ---------------------------------------------------------------------------- #

#
# Subroutines
#

# Makefile header
def makefile_header(name,stamp):

 return """#
# Makefile for ABINIT                                      -*- Automake -*-
#

# Generated by %s on %s

#
# IMPORTANT NOTE
#
# Any manual change to this file will systematically be overwritten.
# Please modify the %s script or its config file instead.
#

#
# If you want to execute a range of tests instead of a whole series, you
# may use the keywords "start", "stop" and "dirname" along with make, e.g.:
#
#    make v1 start=100 stop=104 dirname=root_name_for_the_test_directory
#
# To execute only one test, just omit either start or stop.
# By default, the dirname is the hostname
#
# Default host name for test output directories
dirname = `hostname`

# Main test scripts
run_basic_tests = timeout="$(nightly_timeout)" $(PERL) \\
 $(top_srcdir)/tests/Scripts/run-basic-tests.pl
run_standard_tests = timeout="$(nightly_timeout)" $(PERL) \\
 $(top_srcdir)/tests/Scripts/run-standard-tests.pl
run_parallel_tests = $(BOURNE_SHELL) \\
 $(top_srcdir)/tests/Scripts/wrap-parallel-tests.sh

# External libraries
run_bigdft_tests = $(run_standard_tests) $(dirname) \\
 $(abinit_builddir)/src/main $(abinit_srcdir)/tests bigdft $(start) $(stop)
run_netcdf_tests = $(BOURNE_SHELL) \\
 $(top_srcdir)/tests/Scripts/run-netcdf-tests.sh
run_xmlf90_tests = $(run_basic_tests) xmlf90 6 $(abinit_srcdir)

# Display help by default
all_targets all help:
	@cat $(top_srcdir)/doc/help_make/help_make_tests

""" % (name,stamp,name)

# File lists
def file_list(name,dir):

 list = "%s =\n" % (name)
 tmp  = commands.getoutput("cd tests && find %s -type d -o -path '%s/,,*' -o -path '%s/test.cnf' -prune -o -print 2> /dev/null" % (dir,dir,dir))
 if ( tmp == "" ):
  list += "\n"
 else:
  list += tmp
  list = re.sub("\n"," \\\n\t",list)+"\n\n"

 return """# Files from "%s"\n%s""" % (dir,list)



# Built-in tests
def built_in_tests():

 return """# Built-in tests (1 to 5)
tests_in tests: $(psps_for_tests) $(tests_in_inps)
	@if test ! -e built-in; then mkdir -p built-in; fi
	@for bit in 1 2 3 4 5; do \
	   echo "Running built-in test $${bit}"; \
	   $(run_basic_tests) built-in $${bit} $(abinit_srcdir); \
	 done

"""



# External library tests
def external_tests(lib,test_alias):

 return """# External library tests: %s
if DO_ENABLE_%s
tests_%s %s: $(psps_for_tests) $(tests_%s_inps)
	@if test ! -e %s; then mkdir -p %s; fi
	@$(run_%s_tests)
endif

""" % (lib,lib.upper(),lib,test_alias,lib,lib,lib,lib)



# Optional library tests
def optional_tests(lib,test_alias):

 return """# Optional library tests: %s
if DO_ENABLE_%s
tests_%s %s: $(psps_for_tests) $(tests_%s_inps)
	@if test ! -e %s; then mkdir -p %s; fi
	$(run_standard_tests) $(dirname) $(abinit_builddir)/src/main $(abinit_srcdir)/tests %s $(start) $(stop)
endif

""" % (lib,lib.upper(),lib,test_alias,lib,lib,lib,lib)



# Test targets
def tests_target(dir,test_alias):

 return """# The "%s" series
tests_%s %s: $(tests_%s_inps) $(psps_for_tests)
	@if test ! -e %s; then mkdir -p %s; fi
	rm -rf %s/*/*SCR
	$(run_standard_tests) $(dirname) $(abinit_builddir)/src/main $(abinit_srcdir)/tests %s $(start) $(stop)

""" % (dir,dir,test_alias,dir,dir,dir,dir,dir)



# Parallel tests
def parallel_tests(test_alias):

 return """tests_paral %s: $(psps_for_tests) $(tests_paral_inps)
	@if test ! -e paral; then mkdir -p paral; fi
	$(run_parallel_tests) $(paral_host) $(paral_mode) $(start) $(stop)

""" % (test_alias)



def install_tests():
 tmp = "install-data-local:\n\t$(INSTALL) -d -m 755 $(DESTDIR)$(abinit_chkdir)"
 tmpdir = re.compile(",.*")
 vimswp = re.compile("\..*\.swp")

 # Find files to install
 for root,dirs,files in os.walk("tests"):
  # Clean-up lists
  if ( "Makefile.am" in files ):
   files.remove("Makefile.am")
  if ( "Makefile.in" in files ):
   files.remove("Makefile.in")
  if ( "Makefile" in files ):
   files.remove("Makefile")

  # We don't want to distribute nor install temporary test directories
  for sub in dirs:
   if tmpdir.match(sub):
    dirs.remove(sub)

  # Relative root
  rel = re.sub("^tests","",root)

  if ( not re.match(",,",rel) ):
   # Install subdirectories
   for sub in dirs:
    tmp += "\n\t$(INSTALL) -d -m 755 $(DESTDIR)$(abinit_chkdir)%s/%s" % \
     (rel,sub)

   # Install data files
   for dat in files:
    if ( not vimswp.match(dat) ):
     if ( dat == "tests.env.in" ):
      src = "$(top_builddir)/tests"
      dat = dat.replace(".in","")
     else:
      src = "$(srcdir)"

     tmp += "\n\t$(INSTALL_DATA) '%s%s/%s' " % (src,rel,dat) \
         +  "'$(DESTDIR)$(abinit_chkdir)%s'" % (rel)

 tmp += "\n"

 return tmp



# ---------------------------------------------------------------------------- #

#
# Main program
#

# Initial setup
my_name    = "make-makefiles-tests"
my_configs = ["config/specs/tests.cf"]
my_output  = "tests/Makefile.am"

# Check if we are in the top of the ABINIT source tree
if ( not os.path.exists("configure.ac") or
     not os.path.exists("src/main/abinit.F90") ):
 print "%s: You must be in the top of the ABINIT source tree." % my_name
 print "%s: Aborting now." % my_name
 sys.exit(1)

# Read config file(s)
for cnf in my_configs:
 if ( os.path.exists(cnf) ):
  execfile(cnf)
 else:
  print "%s: Could not find config file (%s)." % (my_name,cnf)
  print "%s: Aborting now." % my_name
  sys.exit(2)

# What time is it?
now = strftime("%Y/%m/%d %H:%M:%S +0000",gmtime())

# Start to write tests/Makefile.am
mf = file(my_output,"w")
mf.write(makefile_header(my_name,now))

# Prepare EXTRA_DIST target
ext = "EXTRA_DIST = \\\n\t$(tests_scripts)" + \
 " \\\n\t$(psps_for_tests) \\\n\t$(tests_in_inps)"

# Prepare clean-local target
cln = "clean-local:\n\trm -rf built-in/,,*\n"

# Write file lists and targets
mf.write(file_list("tests_scripts","Scripts"))
mf.write(file_list("psps_for_tests","Psps_for_tests"))
mf.write(file_list("tests_in_inps","built-in"))
mf.write(built_in_tests())

for dir in abinit_tests:
 ext += " \\\n\t$(tests_%s_inps)" % (dir)
 cln += "\trm -rf %s/,,*\n" % (dir)

 if ( dir in abitests_specs ):
  specs = abitests_specs[dir]
 else:
  specs = ABI_TST_NIL

 mf.write(file_list("tests_%s_inps" % (dir),dir))
 if ( (specs & ABI_TST_MPI) == 0 ):
  if ( (specs & ABI_TST_EXT) != 0 ):
   mf.write(external_tests(dir,abinit_tests[dir]))
  elif ( (specs & ABI_TST_OPT) != 0 ):
   mf.write(optional_tests(dir,abinit_tests[dir]))
  else:
   mf.write(tests_target(dir,abinit_tests[dir]))
 else:
  mf.write(parallel_tests(abinit_tests[dir]))

# Write EXTRA_DIST, install-data-local and clean-local
ext += "\n\n"
cln += "\n"
mf.write(ext)
mf.write(install_tests())
mf.write("\n"+cln)

add = "config/makefiles/tests.am"
if ( os.path.exists(add) ):
 mf.write(file(add,"r").read())

mf.close()
