#!/usr/bin/env python
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import print_function

import argparse
import time
from threading import Thread
import os.path
import collections
import re
import os

import Report
import config

# WARNING
#
# If you are editing this code, please be aware that commands passed to `run`
# should not use single quotes, this will break and end badly as the final
# command looks like `ssh 'host' 'some command - single quote will break it'`.
# Also please be aware that `run` uses `.format` to change `{host}` in commands
# into actual host name it is running on, running `.format` on strings using
# `{host}`, for example including `host_code_path` will not work.
#
# Also this code assumes master_base_path is available to all testing machines
# and is mounted in the same place on all of them.
#
# Getting rid of this restrictions without making the code much more complicated
# is very welcome.

# This is configured in user configuration file.

local = None
qfile_set = None
other_set = None
remote_set = None
all_set = None

master_base_path = None
host_base_path = None
runtest_dir = os.getcwd()

# End of user configurated things.

ant_path = None
arc_path = None
phutil_path = None
code_path = None
report_path = None
host_code_path = None
ivy_path = None

def read_conf(config_file):
    global local, qfile_set, other_set, remote_set, all_set
    global master_base_path, host_base_path
    global ant_path, arc_path, phutil_path, code_path, report_path, host_code_path, ivy_path

    if config_file is not None:
        config.load(config_file)
    else:
        config.load()

    local = config.local
    qfile_set = config.qfile_set
    other_set = config.other_set
    remote_set = config.remote_set
    all_set = config.all_set

    master_base_path = config.master_base_path
    host_base_path = config.host_base_path

    if 'HIVE_PTEST_SUFFIX' in os.environ:
        suffix = os.environ['HIVE_PTEST_SUFFIX']
        master_base_path += '-' + suffix
        host_base_path  += '-' + suffix

    ant_path = master_base_path + '/apache-ant-1.8.4'
    arc_path = master_base_path + '/arcanist'
    phutil_path = master_base_path + '/libphutil'
    code_path = master_base_path + '/trunk'
    report_path = master_base_path + '/report/' + time.strftime('%m.%d.%Y_%H:%M:%S')
    host_code_path = host_base_path + '/trunk-{host}'
    ivy_path = master_base_path + '/.ivy2'

    # Setup of needed environmental variables and paths

    # Proxy
    if args.http_proxy is not None:
      all_set.export('http_proxy', args.http_proxy + ':' + args.http_proxy_port)
      all_set.export('https_proxy', args.http_proxy + ':' + args.http_proxy_port)
      all_set.export('ANT_OPTS', get_ant_opts_proxy())

    # Ant
    all_set.export('ANT_HOME', ant_path)
    all_set.add_path(ant_path + '/bin')

    # Arcanist
    all_set.add_path(arc_path + '/bin')

    # Java
    all_set.export('JAVA_HOME', config.java_home)
    all_set.add_path(config.java_home + '/bin')

    # Hive
    remote_set.export('HIVE_HOME', host_code_path + '/build/dist')
    remote_set.add_path(host_code_path + '/build/dist/bin')

def get_ant_opts_proxy():
  cmd  = ' -Dhttp.proxyHost='  + args.http_proxy
  cmd += ' -Dhttp.proxyPort='  + args.http_proxy_port
  cmd += ' -Dhttps.proxyHost=' + args.http_proxy
  cmd += ' -Dhttps.proxyPort=' + args.http_proxy_port
  return cmd

def get_ant():
    # Gets Ant 1.8.4 from one of Apache mirrors.
    print('\n-- Installing Ant 1.8.4\n')

    if local.run('test -d "{0}"'.format(ant_path), warn_only = True,
            abandon_output = False) is None:
        local.run('mkdir -p "{0}"'.format(master_base_path))
        local.cd(master_base_path)
        local.run('curl "http://apache.osuosl.org//ant/binaries/apache-ant-1.8.4-bin.tar.gz" | tar xz')
    else:
        print('\n  Ant 1.8.4 already installed\n')

def get_arc():
    # Gets latest Arcanist and libphtuil from their Git repositories.
    print('\n-- Updating Arcanist installation\n')

    if local.run('test -d "{0}"'.format(arc_path), warn_only = True,
            abandon_output = False) is None:
        local.run('mkdir -p "{0}"'.format(os.path.dirname(arc_path)))
        local.run('git clone https://github.com/facebook/arcanist.git "{0}"'
                .format(arc_path))

    if local.run('test -d "{0}"'.format(phutil_path), warn_only = True,
            abandon_output = False) is None:
        local.run('mkdir -p "{0}"'.format(os.path.dirname(phutil_path)))
        local.run('git clone https://github.com/facebook/libphutil.git "{0}"'
                .format(phutil_path))

    local.cd(arc_path)
    local.run('git pull https://github.com/facebook/arcanist.git')
    local.cd(phutil_path)
    local.run('git pull https://github.com/facebook/libphutil.git')

def get_clean_hive():
    # Gets latest Hive from Apache Git repository and cleans the repository
    # (undo of any changes and removal of all generated files).  Also runs
    # `arc-setup` so the repo is ready to be used.
    print('\n-- Updating Hive repo\n')

    local.cd(code_path)
    if local.run('test -d "{0}"'.format(code_path), warn_only = True,
            abandon_output = False) is None:
      local.run('mkdir -p "{0}"'.format(os.path.dirname(code_path)))
      local.run('git clone http://git.apache.org/hive.git "{0}"'.format(code_path))
    else:
      # Clean repo and checkout to t he last revision
      local.run('git reset --hard HEAD')
      local.run('git clean -dffx')
      local.run('git pull')

    local.run('ant arc-setup')

def copy_local_hive():
    # Copy local repo to the destination path instead of using git clone
    if local.run('test -d "{0}"'.format(code_path), warn_only = True,
            abandon_output = False) is None:
      local.run('mkdir -p "{0}"'.format(os.path.dirname(code_path)))
    local.run('rm -rf "{0}"'.format(code_path), warn_only = True)
    local.run('mkdir -p "{0}"'.format(code_path))
    local.run('echo "{0}"'.format(runtest_dir))
    local.cd(runtest_dir)
    local.run('cp -rf * "{0}"'.format(code_path))
    local.cd(code_path)
    local.run('ant arc-setup')

def prepare_for_reports():
    # Generates directories for test reports.  All test nodes will copy results
    # to this directories.
    print('\n-- Creating a directory for JUnit reports\n')
    # Remove previous reports that might be there.
    local.run('rm -rf "{0}"'.format(report_path), warn_only = True)
    local.run('mkdir -p "{0}/logs"'.format(report_path))
    local.run('mkdir -p "{0}/out/clientpositive"'.format(report_path))
    local.run('mkdir -p "{0}/out/clientnegative"'.format(report_path))

def patch_hive(patches = [], revision = None):
    # Applies given patches to the Hive repo.  Revision means a Differential
    # revision, patches list is a list of paths to patches on local file system.
    #
    # Allowing multiple revisions and patches would complicate things a little
    # (order of applied patches should be preserved, but argparse will split
    # them into two lists) so only multiple local patches are allowed.
    # Shouldn't be a big problem as you can use `arc export` to get the patches
    # locally.
    local.cd(code_path)
    if revision is not None:
        print('\n-- Patching Hive repo using a Differential revision\n')
        revision = revision.upper()
        if not revision.startswith('D'):
            revision = 'D' + revision
        local.run('arc patch "{0}"'.format(revision))
    if patches:
        print('\n-- Patching Hive repo using a patch from local file system\n')
        for patch in patches:
            local.run('patch -rf -p0 < "{0}"'.format(patch))

def build_hive():
    print('\n-- Building Hive\n')
    local.cd(code_path)
    cmd = 'ant -Divy.default.ivy.user.dir={0} '.format(ivy_path)
    if args.very_clean:
      cmd += 'very-clean '
    else:
      cmd += 'clean '
    cmd += 'package'
    local.run(cmd)

def propagate_hive():
    # Expects master_base_path to be available on all test nodes in the same
    # place (for example using NFS).
    print('\n-- Propagating Hive repo to all hosts\n')
    print(host_code_path)
    print(code_path)

    remote_set.run('rm -rf "{0}"'.format(host_code_path))
    remote_set.run('mkdir -p "{0}"'.format(host_code_path))
    remote_set.run('cp -r "{0}/*" "{1}"'.format(
                    code_path, host_code_path))

    # It should avoid issues with 'ivy publish' exceptions during testing phase.
    remote_set.run('cp -r "{0}" "{1}"'.format(ivy_path, host_code_path))


def segment_tests(path):
    # Removes `.q` files that should not be run on this host.  The huge shell
    # command is slow (not really suprising considering amount of forking it has
    # to do), you are welcome to make it better=).
    local.cd(code_path + path)
    tests = local.run('ls -1', quiet = True, abandon_output = False).strip().split('\n')

    qfile_set.cd(host_code_path + path)
    test_splits = [[] for i in range(len(qfile_set))]
    i = 0
    for test in tests:
        test_splits[i].append(test)
        i = (i + 1) % len(qfile_set)
    cmd = []
    for i in range(len(qfile_set)):
        host = qfile_set.conn[i].hostname
        cmd.append('if [[ "{host}" != "' + host + '" ]]; then rm -f ' + ' '.join(test_splits[i]) + '; fi')
    cmd = ' && '.join(cmd)
    # The command is huge and printing it out is not very useful, using wabbit
    # hunting mode.
    qfile_set.run(cmd, vewy_quiet = True)

def prepare_tests():
    print('\n-- Preparing test sets on all hosts\n')
    segment_tests('/ql/src/test/queries/clientpositive')
    segment_tests('/ql/src/test/queries/clientnegative')

def collect_log(name):
    # Moves JUnit log to the global logs directory.
    #
    # This has the same restriction on master_base_path as propagate_hive.
    new_name = name.split('.')
    new_name[-2] += '-{host}'
    new_name = '.'.join(new_name)
    qfile_set.cd(host_code_path + '/build/ql/test')
    # If tests failed there may be no file, so warn only if `cp` is having
    # problems.
    qfile_set.run(
        'cp "' + name + '" "' + report_path + '/logs/' + new_name + '" || ' +
        'touch "' + report_path + '/logs/{host}-' + name + '.fail"'
    )
    # Get the hive.log too.
    qfile_set.cd(host_code_path + '/build/ql/tmp')
    qfile_set.run('cp "hive.log" "' + report_path + '/logs/hive-{host}-' + name + '.log"',
            warn_only = True)

def collect_out(name, desc_name):
    # Moves `.out` file (test output) to the global logs directory.
    #
    # This has the same restriction on master_base_path as propagate_hive.
    qfile_set.cd(host_code_path + '/' + name)
    # Warn only if no files are found.
    qfile_set.run('mkdir -p "' + report_path + '/' + desc_name + '/out/' + '"', warn_only = True)
    qfile_set.run('cp * "' + report_path + '/' + desc_name + '/out/' + '"', warn_only = True)

def run_tests():
    # Runs TestCliDriver and TestNegativeCliDriver testcases.
    print('\n-- Running .q file tests on all hosts\n')

    # Using `quiet` because output of `ant test` is not very useful when we are
    # running on many hosts and it all gets mixed up.  In case of an error
    # you'll get last lines generated by `ant test` anyway (might be totally
    # irrelevant if one of the first tests fails and Ant reports a failure after
    # running all the other test, fortunately JUnit report saves the Ant output
    # if you need it for some reason).

    remote_ivy_path = '$(pwd)/.ivy2'

    qfile_set.cd(host_code_path)
    qfile_set.run('ant -Divy.default.ivy.user.dir={0} -Dtestcase=TestCliDriver test'.format(remote_ivy_path), quiet = True, warn_only = True)
    collect_log('TEST-org.apache.hadoop.hive.cli.TestCliDriver.xml')
    collect_out('build/ql/test/logs/clientpositive', 'TestCliDriver')

    qfile_set.cd(host_code_path)
    qfile_set.run('ant -Divy.default.ivy.user.dir={0} -Dtestcase=TestNegativeCliDriver test'.format(remote_ivy_path), quiet = True, warn_only = True)
    collect_log('TEST-org.apache.hadoop.hive.cli.TestNegativeCliDriver.xml')
    collect_out('build/ql/test/logs/clientnegative', 'TestNegativeCliDriver')

def run_other_tests():
    # Runs all other tests that run_test doesn't run.

    def get_other_list():
        local.cd(code_path)
        # Generate test classes in build.
        local.run('ant -Dtestcase=nothing test')

        if (args.singlehost):
          tests = local.run(' | '.join([
              'find build/*/test/classes -name "Test*.class"',
              'sed -e "s:[^/]*/::g"',
              'grep -v TestSerDe.class',
              'grep -v TestHiveMetaStore.class',
              'grep -v TestBeeLineDriver.class',
              'grep -v TestHiveServer2Concurrency.class',
              'grep -v TestCliDriver.class',
              'grep -v TestNegativeCliDriver.class',
              'grep -v ".*\$.*\.class"',
              'sed -e "s:\.class::"'
          ]), abandon_output = False)
          return tests.split()
        else:
          tests = local.run(' | '.join([
              'find build/*/test/classes -name "Test*.class"',
              'sed -e "s:[^/]*/::g"',
              'grep -v TestSerDe.class',
              'grep -v TestHiveMetaStore.class',
              'grep -v TestBeeLineDriver.class',
              'grep -v TestHiveServer2Concurrency.class',
              'grep -v TestCliDriver.class',
              'grep -v TestNegativeCliDriver.class',
              'grep -v ".*\$.*\.class"',
              'grep -v TestSetUGIOnBothClientServer.class',
              'grep -v TestSetUGIOnOnlyClient.class',
              'grep -v TestSetUGIOnOnlyServer.class',
              'grep -v TestRemoteHiveMetaStore',
              'grep -v TestEmbeddedHiveMetaStore',
              'sed -e "s:\.class::"'
          ]), abandon_output = False)
          return tests.split()

    def segment_other():
        other_set.run('mkdir -p ' + report_path + '/TestContribCliDriver', warn_only = True)
        other_set.run('mkdir -p ' + report_path + '/TestContribCliDriver/positive', warn_only = True)
        other_set.run('mkdir -p ' + report_path + '/TestContribCliDriver/negative', warn_only = True)
        other_set.run('mkdir -p ' + report_path + '/TestHBaseCliDriver', warn_only = True)

        # Split all test cases between hosts.
        def get_command(test):
            return '; '.join([
                'ant -Divy.default.ivy.user.dir=$(pwd)/.ivy2 -Dtestcase=' + test + ' test',

                'cp "`find . -name "TEST-*.xml"`" "' + report_path + '/logs/" || ' +
                'touch "' + report_path + '/logs/{host}-' + test + '.fail"',

                'cp "build/ql/tmp/hive.log" "' + report_path + '/logs/hive-{host}-' + test + '.log"',

                'cp "build/contrib/test/logs/contribclientnegative/*" "' + report_path + '/TestContribCliDriver/negative 2>/dev/null"',

                'cp "build/contrib/test/logs/contribclientpositive/*" "' + report_path + '/TestContribCliDriver/positive 2>/dev/null"',

                'cp "build/hbase-handler/test/logs/hbase-handler/*" "' + report_path + '/TestHBaseCliDriver/ 2>/dev/null"'
            ])

        cmd = []
        i = 0
        for test in get_other_list():
            # Special case, don't run minimr tests in parallel.  They will run
            # on the first host, and no other tests will run there (unless we
            # have a single host).
            #
            # TODO: Real fix would be to allow parallel runs of minimr tests.
            if len(other_set) > 1:
                if re.match('.*minimr.*', test.lower()):
                    host = other_set.conn[0].hostname
                else:
                    i = (i + 1) % len(other_set)
                    if i == 0:
                        i = 1
                    host = other_set.conn[i].hostname
            else:
                # We are running on single host.
                host = other_set.conn[0].hostname
            cmd.append(
                'if [[ "{host}" == "' + host + '" ]]; then ' +
                get_command(test) +
                '; fi'
            )
        return ' ; '.join(cmd)

    command = segment_other()
    other_set.cd(host_code_path)
    # See comment about quiet option in run_tests.
    other_set.run(command, quiet = True, warn_only = True)

def generate_report(one_file_report = False):
    # Uses `Report.py` to create a HTML report.
    print('\n-- Generating a test report\n')
    local.run('cp "' + master_base_path + '/templogs/* " "'+ report_path + '/logs/" ', warn_only = True)

    # Call format to remove '{{' and '}}'.
    path = os.path.expandvars(report_path.format())
    CmdArgs = collections.namedtuple('CmdArgs', ['one_file', 'log_dir', 'report_dir'])
    args = CmdArgs(
        one_file = one_file_report,
        log_dir = '{0}/logs'.format(path),
        report_dir = path
    )
    Report.make_report(args)

    print('\n-- Test report has been generated and is available here:')
    print('-- "{0}/report.html"'.format(path))
    print()

def stop_tests():
    # Brutally stops tests on all hosts, something more subtle would be nice and
    # would allow the same user to run this script multiple times
    # simultaneously.
    print('\n-- Stopping tests on all hosts\n')
    remote_set.run('killall -9 java', warn_only = True)

def remove_code():
    # Running this only on one connection per host so there are no conflicts
    # between several `rm` calls.  This removes all repositories, it would have
    # to be changed if we were to allow multiple simultaneous runs of this
    # script.

    print('\n-- Removing Hive code from all hosts\n')
    # We could remove only `host_code_path`, but then we would have abandoned
    # directories after lowering number of processes running on one host.
    cmd = 'rm -rf "' + host_base_path + '"'
    cmd = 'if [[ `echo "{host}" | grep -q -- "-0$"; echo "$?"` -eq "0" ]]; then ' + \
            cmd + '; fi'
    remote_set.run(cmd)

def overwrite_results():
    # Copy generated `.q.out` files to master repo.

    local.cd(code_path)
    expanded_path = local.run('pwd', abandon_output = False)
    print('\n-- Copying generated `.q.out` files to master repository: ' +
            expanded_path)

    for name in ['clientpositive', 'clientnegative']:
        local.cd(report_path + '/out/' + name)
        # Don't panic if no files are found.
        local.run('cp * "' + code_path + '/ql/src/test/results/' + name + '"',
                warn_only = True)

def save_svn_info():
  if args.svn_info:
    local.cd(master_base_path + '/trunk')
    local.run('git show --summary > "{0}"'.format(report_path + '/svn-info'))

def save_patch():
  if args.save_patch:
    local.cd(code_path)
    local.run('git add --all')
    local.run('git diff --no-prefix HEAD > "{0}"'.format(report_path + '/patch'))

# -- Tasks that can be called from command line start here.

def cmd_prepare(patches = [], revision = None):
    get_ant()
    get_arc()
    if (args.copylocal):
      copy_local_hive()
    else :
      get_clean_hive()
      patch_hive(patches, revision)

    build_hive()
    propagate_hive()
    prepare_tests()

def cmd_run_tests(one_file_report = False):
    prepare_for_reports()
    save_svn_info()
    save_patch()

    t = Thread(target = run_other_tests)
    t.start()
    run_tests()
    t.join()

    if args.overwrite:
        overwrite_results()

    generate_report(one_file_report)

def cmd_test(patches = [], revision = None, one_file_report = False):
    cmd_prepare(patches, revision)

    if args.singlehost==False:
      local.cd(master_base_path + '/trunk')
      local.run('chmod -R 777 *');
      local.run('rm -rf "' + master_base_path + '/templogs/"')
      local.run('mkdir -p "' + master_base_path + '/templogs/"')
      tests = ['TestRemoteHiveMetaStore','TestEmbeddedHiveMetaStore','TestSetUGIOnBothClientServer','TestSetUGIOnOnlyClient','TestSetUGIOnOnlyServer']

      for test in tests:
        local.run('sudo -u root ant -Divy.default.ivy.user.dir={0} '.format(ivy_path) + ' -Dtestcase=' + test + ' test')
        local.run('cp "`find . -name "TEST-*.xml"`" "' + master_base_path + '/templogs/"')

    cmd_run_tests(one_file_report)

def cmd_stop():
    stop_tests()

def cmd_remove():
    remove_code()

parser = argparse.ArgumentParser(description =
        'Hive test farm controller.')
parser.add_argument('--config', dest = 'config',
        help = 'Path to configuration file')
parser.add_argument('--prepare', action = 'store_true', dest = 'prepare',
        help = 'Builds Hive and propagates it to all test machines')
parser.add_argument('--run-tests', action = 'store_true', dest = 'run_tests',
        help = 'Runs tests on all test machines')
parser.add_argument('--test', action = 'store_true', dest = 'test',
        help = 'Same as running `prepare` and then `run-tests`')
parser.add_argument('--report-name', dest = 'report_name',
        help = 'Store report and logs directory called `REPORT_NAME`')
parser.add_argument('--stop', action = 'store_true', dest = 'stop',
        help = 'Kill misbehaving tests on all machines')
parser.add_argument('--remove', action = 'store_true', dest = 'remove',
        help = 'Remove Hive trunk copies from test machines')
parser.add_argument('--revision', dest = 'revision',
        help = 'Differential revision to test')
parser.add_argument('--patch', dest = 'patch', nargs = '*',
        help = 'Patches from local file system to test')
parser.add_argument('--one-file-report', dest = 'one_file_report',
        action = 'store_true',
        help = 'Generate one (huge) report file instead of multiple small ones')
parser.add_argument('--overwrite', dest = 'overwrite', action = 'store_true',
        help = 'Overwrite result files in master repo')
parser.add_argument('--copylocal', dest = 'copylocal', action = 'store_true',
        help = 'Copy local repo instead of using git clone and git hub')
parser.add_argument('--singlehost', dest = 'singlehost', action = 'store_true',
        help = 'Only run the test on single host, It is the users '
               'responsibility to make sure that the conf. file does not '
               'contain multiple hosts. '
               'The script is not doing any validation. When --singlehost is set '
               'the script should not be run using sudo.')
parser.add_argument('--very-clean', action = 'store_true', dest = 'very_clean',
        help = 'Build hive with `very-clean` option')
parser.add_argument('--svn-info', dest = 'svn_info', action = 'store_true',
        help = 'Save result of `svn info` into ${report_path}/svn-info')
parser.add_argument('--save-patch', dest = 'save_patch', action = 'store_true',
        help = 'Save applied patch into ${report_path}/patch')
parser.add_argument('--http-proxy', dest = 'http_proxy',
        help = 'Proxy host')
parser.add_argument('--http-proxy-port', dest = 'http_proxy_port',
        help = 'Proxy port')

args = parser.parse_args()

read_conf(args.config)

if args.report_name:
    report_path = '/'.join(report_path.split('/')[:-1] + [args.report_name])

if args.prepare:
    cmd_prepare(args.patch, args.revision)
elif args.run_tests:
    cmd_run_tests(args.one_file_report)
elif args.test:
    cmd_test(args.patch, args.revision, args.one_file_report)
elif args.stop:
    cmd_stop()
elif args.remove:
    cmd_remove()
else:
  parser.print_help()

