# -*- Python -*-

import platform
import os
import subprocess

import lit.formats

# Configuration file for the 'lit' test runner.

def which(command, paths = None):
    """which(command, [paths]) - Look up the given command in the paths string
    (or the PATH environment variable, if unspecified)."""

    if paths is None:
        paths = os.environ.get('PATH','')

    # Check for absolute match first.
    if os.path.exists(command):
        return command

    # Would be nice if Python had a lib function for this.
    if not paths:
        paths = os.defpath

    # Get suffixes to search.
    pathext = os.environ.get('PATHEXT', '').split(os.pathsep)

    # Search the paths...
    for path in paths.split(os.pathsep):
        for ext in pathext:
            p = os.path.join(path, command + ext)
            if os.path.exists(p):
                return p

    return None

###
# Retrieve expected values from lit.site.cfg

srcroot = os.path.dirname(os.path.abspath(__file__))
srcroot = os.path.normpath(srcroot)

###
# Basic Configuration Parameters

# name: The name of this test suite.
config.name = 'swift-package-tests'

# testFormat: The test format to use to interpret tests.
config.test_format = lit.formats.ShTest(execute_external = False)

# suffixes: A list of file extensions to treat as test files.
#
# We override this in specific subdirectories to change what we test.
config.suffixes = [".txt", ".py"]

# excludes: A list of directories to exclude from the testsuite. The 'Inputs'
# subdirectories contain auxiliary inputs for various tests in their parent
# directories.
config.excludes = ['Inputs']

# test_source_root: The root path where tests are located.
config.test_source_root = os.path.join(srcroot)

# test_source_root: The root path where tests are executing.
config.test_exec_root = "/tmp/swift-package-tests"

# The triple is used during XFAIL processing.  If the triple
# specified here matches one of the XFAIL triples, a failing
# test is allowed to fail.  We don't actually need the whole
# thing, just enough to identify Linux, so for now only fill
# in enough to handle that.
#
# TODO figure out how to grab the whole triple for the build
# target and stick it in here.
if platform.system() == 'Linux':
    config.target_triple = 'linux'
elif platform.system() == 'Darwin':
    config.target_triple = 'darwin'


# On Darwin, always push SDKROOT in the environment.
#
# FIXME: Eventually, when we use xcrun to launch the toolchain items, this
# should go away.
if platform.system() == "Darwin":
    config.environment["SDKROOT"] = subprocess.check_output(
        ["xcrun", "--sdk", "macosx", "--show-sdk-path"]).strip()

###

# Use features like this in lit:
#   # REQUIRES: platform=<platform>
# where <platform> is Linux or Darwin
# Add a platform feature.
config.available_features.add("platform="+platform.system())

# Check if 'pexpect' is available.
have_pexpect = False
try:
    import pexpect
    have_pexpect = True
except ImportError as e:
    pass
if have_pexpect:
    config.available_features.add("have-pexpect")
else:
    lit_config.note("'pexpect' module unavailable, skipping related tests")

# For tests that need access to the outside world, let them know if
# that's possible
if lit_config.params.get("have-network"):
    config.available_features.add("have-network")
    
###

# Get the package path.
package_path = lit_config.params.get("package-path")
if package_path is None:
    lit_config.fatal("'--param package-path=PATH' is required")
package_path = os.path.abspath(package_path)
# if platform.system() == "Darwin":
#     package_path = os.path.join(package_path, "Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain")
lit_config.note("testing package: %r" % (package_path,))

# Find the path to FileCheck. We just pick any one out of the build directory.
swift_build_path =  os.path.join(srcroot, "..", "build")
filecheck_path = lit_config.params.get("filecheck")
if filecheck_path is None:
    for variant in os.listdir(swift_build_path):
        variant_path = os.path.join(swift_build_path, variant)
        for tree in os.listdir(variant_path):
            if tree.startswith("llvm-"):
                path = os.path.join(variant_path, tree, "bin", "FileCheck")
                if os.path.exists(path):
                    filecheck_path = path
                    break
if filecheck_path is None:
    lit_config.fatal("unable to locate FileCheck, '--param filecheck=PATH' is required")

# Use the default Swift src layout if swiftpm is not provided as a
# param
swiftpm_srcdir = lit_config.params.get("swiftpm-srcdir")
if swiftpm_srcdir is None:
    swiftpm_srcdir = os.path.join(srcroot, "..", "swiftpm")
if os.path.exists(swiftpm_srcdir):
    config.available_features.add("have-swiftpm")
    config.substitutions.append( ('%{swiftpm_srcdir}', swiftpm_srcdir) )
    
# Find the tools we need.
lit_config.note("testing using 'FileCheck': %r" % (filecheck_path,))

swift_path = os.path.join(package_path, "usr", "bin", "swift")
lit_config.note("testing using 'swift': %r" % (swift_path,))

swiftc_path = os.path.join(package_path, "usr", "bin", "swiftc")
lit_config.note("testing using 'swiftc': %r" % (swiftc_path,))

lldb_path = os.path.join(package_path, "usr", "bin", "lldb")
lit_config.note("testing using 'lldb': {}".format(lldb_path))
                    
# Verify they exist.
if not os.path.exists(swift_path):
    lit_config.fatal("swift does not exist!")
if not os.path.exists(swiftc_path):
    lit_config.fatal("swiftc does not exist!")
if not os.path.exists(filecheck_path):
    lit_config.fatal("filecheck does not exist!")
if not os.path.exists(lldb_path):
    lit_config.fatal("lldb does not exist!")

# Define our supported substitutions.
config.substitutions.append( ('%{lldb}', lldb_path) )
config.substitutions.append( ('%{swift}', swift_path) )
config.substitutions.append( ('%{swiftc}', swiftc_path) )
config.substitutions.append( ('%{FileCheck}', filecheck_path) )

###

# Protected against unquoted use of substitutions.
for name in ('swift-build', 'FileCheck'):
  config.substitutions.append((' {0} '.format(name),
                               ' unquoted-command-name-{0} '.format(name)))
