#!/usr/bin/env python2.3
########################################
# The contents of this file are subject to the MLX PUBLIC LICENSE version
# 1.0 (the "License"); you may not use this file except in
# compliance with the License.
# 
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
# the License for the specific language governing rights and limitations
# under the License.
# 
# The Original Source Code is "compClust", released 2003 September 03.
# 
# The Original Source Code was developed by the California Institute of
# Technology (Caltech).  Portions created by Caltech are Copyright (C)
# 2002-2003 California Institute of Technology. All Rights Reserved.
########################################
#
#        Author: Diane Trout
# Last Modified: $Date: 2003/09/04 01:51:33 $
#

"""
Recursively executes a testing framework for the python code base.

This module is responsible for recursively finding and executing all python
scripts of the form Test*.py.  Each module in the code base should have a
corresponding test file.  This is the major source of regression testing.
"""

import imp
import re
import os
import string
import sys
import types
import unittest

#import compClust

# defaults (automated GUI testing causes problems, so we'll turn them off)
suite_args = {
'test_tk': False,
'test_gtk': False
}

if os.path.isdir(os.path.join(os.getcwd(), 'compClust','tests')):
  base_dir = os.path.join(os.getcwd(), 'compClust')
elif os.path.isdir(os.path.join(os.getcwd(), '..', '..', 'compClust','tests')):
  base_dir = os.path.join(os.getcwd(), '..', '..', 'compClust')
else:
  base_dir = None

def findSubTests(base_directory):
  test_modules = []
  test_regexp = re.compile("^test.*\.py$")

  def isTestModule(t):
    # skip our master test program, but load any other test module
    if t == "testEverything.py":
      return 0
    elif test_regexp.match(t):
      return 1
    else:
      return 0
    
  # for all the items in our package
  for path, dirs, files in os.walk(base_directory):
    # skip version control directories
    if path[-4:] == '.svn' or path[-3:] == 'CVS':
      continue

    for f in files:
      if isTestModule(f):
        test_modules.append(os.path.join(path, f))

  return test_modules

def loadTestModule(pathname):
  dir_name, filename = os.path.split(pathname)
  base_name, extention = os.path.splitext(filename)
  os.chdir(dir_name)

  module_info = imp.find_module(base_name, [dir_name])
  module_stream, module_name, module_description = module_info
  module = imp.load_module(base_name,
                           module_stream,
                           module_name,
                           module_description)
  return module

def loadAllTestSuites():
  # recursively search through the subdirectories for all the Test*.py files
  tests = findSubTests(base_dir)
  # find all the tests available for running
  test_cases = []
  for current_test_file in tests:
    current_test_module = loadTestModule(current_test_file)
    try:
      current_test_suite = current_test_module.suite(**suite_args)
    except AttributeError, e:
      print "test %s didn't have a suite function" % (current_test_file)
      continue
    except TypeError, e:
      print "test %s didn't have suite(**kw)" % (current_test_file)
      raise TypeError(e)
  
    if current_test_suite is not None:
      test_cases.append(current_test_suite)

  # construct the complete test suite
  test_suite = unittest.TestSuite()
  test_suite.addTests(test_cases)
  return test_suite
suite = loadAllTestSuites()


def set_jpl_paths():
  """See if we have the JPL encumbered clustering algorithms available
  and if so, set up our environment variables
  """
  cwd = os.getcwd()
  commands = [('src/mls/diagem/diagem', 'DIAGEM_COMMAND'),
              ('src/mls/fullem/fullem', 'FULLEM_COMMAND'),
              ('src/mls/kmeans/kmeans', 'KMEANS_COMMAND'),
              ('src/mls/kmedians/kmedians', 'KMEDIANS_COMMAND'),
              ('src/mls/sclust/sclust', 'SCLUST_COMMAND'),
              ('src/mls/tsplit/tsplit', 'TSPLIT_COMMAND'),
              ('src/mls/xclust/xclust', 'XCLUST_COMMAND')]

  for subpath, environment_variable in commands:
    path = os.path.join(cwd, subpath)
    if not os.path.exists(path):
      path = os.path.join(cwd, '../..', subpath)
      if not os.path.exists(path):
        continue
    os.environ[environment_variable] = path
      
def main(args=None):
  """Commandline-like entry point for running test cases
  
  main(['arg1', 'arg2', ...])
  """
  # FIXME: at some point we should add a command line option
  # FIXME: to turn on tk testing
  #set_jpl_paths()
  try:
  #  import testoob
  #  test_framework = testoob
    test_framework = unittest
  except ImportError, e:
    test_framework = unittest
  test_framework.main(defaultTest="loadAllTestSuites")
  
if __name__ == "__main__":
  main(sys.argv)
