# -*- 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", ".md"]

# 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 = ['README.md', 'CONTRIBUTING.md', '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 = lit_config.params.get(
    "test-exec-root",
    "/tmp/swift-integration-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.
config.environment["HOME"] = os.getenv("HOME")
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:
    # If a package wasn't provided, use the current selected toolchain on Darwin.
    if platform.system() == "Darwin":
        package_path = os.path.abspath(
            os.path.join(subprocess.check_output(["xcrun", "--find", "swift"]).strip(), "../../../"))
if package_path is None:
    lit_config.fatal("'--param package-path=PATH' is required")
package_path = os.path.abspath(package_path)
lit_config.note("testing package: %r" % (package_path,))

# Get the path to the llvm binary dir. We use tools from this
# directory (including FileCheck) to test our snapshots. In terms of
# the actual swift build directory, this is not ./, but ./bin. This is
# to potentially allow for an installed llvm binary installation to be
# used when testing.
llvm_bin_dir = lit_config.params.get("llvm-bin-dir")
if llvm_bin_dir is None:
    lit_config.fatal("'--param llvm_bin_dir=PATH' is required")
filecheck_path = os.path.join(llvm_bin_dir, 'FileCheck')
readelf_path = os.path.join(llvm_bin_dir, 'llvm-readelf')
lit_config.note("testing using 'FileCheck': %r" % (filecheck_path,))
lit_config.note("testing using 'readelf': %r" % (readelf_path,))


# 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.

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

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

lldb_path = lit_config.params.get(
    "lldb",
    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):
    if platform.system() == "Darwin":
        lldb_path = subprocess.check_output(["xcrun", "--find", "lldb"]).strip()
    else:
        lit_config.fatal("lldb does not exist!")

# Define our supported substitutions.
config.substitutions.append( ('%{package_path}', package_path) )
config.substitutions.append( ('%{python}', sys.executable) )
config.substitutions.append( ('%{not}', os.path.join(srcroot, "not")) )
config.substitutions.append( ('%{lldb}', lldb_path) )
config.substitutions.append( ('%{swift}', swift_path) )
config.substitutions.append( ('%{swiftc}', swiftc_path) )
config.substitutions.append( ('%{FileCheck}', filecheck_path) )
config.substitutions.append( ('%{readelf}', readelf_path) )

# Add substitutions for swiftpm executables.
swiftpm_build = lit_config.params.get("swiftpm-build")
if swiftpm_build is not None:
    lit_config.note("testing using swiftpm build directory: {}".format(swiftpm_build))
    config.substitutions.append( ('%{swift-build}',  os.path.join(swiftpm_build, "swift-build")) )
    config.substitutions.append( ('%{swift-test}',  os.path.join(swiftpm_build, "swift-test")) )
    config.substitutions.append( ('%{swift-run}',  os.path.join(swiftpm_build, "swift-run")) )
else:
    config.substitutions.append( ('%{swift-build}', swift_path + ' build') )
    config.substitutions.append( ('%{swift-test}', swift_path + ' test') )
    config.substitutions.append( ('%{swift-run}', swift_path + ' run') )

###

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