#!/usr/bin/env python
# encoding: utf-8
"""
Generate TestNG XML files
"""

#
#  Copyright (C) 2009 - 2017 Open Microscopy Environment. All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions
#  are met:
#  1. Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#  2. Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#
#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
#  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
#  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
#  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
#  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
#  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#  SUCH DAMAGE.

import sys
import os

from xml.sax.saxutils import escape
from getopt import getopt, GetoptError

# Handle Python 2.5 built-in ElementTree
try:
    from xml.etree.ElementTree import Element, ElementTree
except ImportError:
    from elementtree.ElementTree import Element, ElementTree


# Configuration options
JAVA_ARGS = "-Xmx2048M"
START_CLASS = "org.testng.TestNG"
DOCTYPE = '<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">'


def usage(error):
    """Prints usage so that we don't have to. :)"""
    cmd = sys.argv[0]
    print """%s
Usage: %s [-f file] <test_class> [target...]
Generates a TestNG XML file against a given set of targets.

Options:
  -f            Reads targets from a file ("-" reads from STDIN)
  -t            Number of parallel threads for TestNG to use (default 2)
  -m            Memory-map files whenever possible

Examples:
  %s -f ~/regular_test_files loci.tests.testng.OpenBytesPerformanceTest ~/testimages/foo.tiff
  find -name '*.tif' | %s -f - loci.tests.testng.OpenBytesPerformanceTest

Report bugs to ome-devel@lists.openmicroscopy.org.uk""" % (error, cmd, cmd, cmd)
    sys.exit(2)


def create_testng_xml_file(test_class, targets, thread_count, in_memory):
    """Creates a temporary file with TestNG XML content for each target."""
    root = Element("suite")
    root.set("name", "targets")
    root.set("parallel", "tests")
    root.set("thread-count", str(thread_count))
    # Add each target to the TestNG XML file
    for target in targets:
        target = target.strip().lstrip()
        test_name = escape(target.replace("/", "_"))
        klass = Element("class")
        klass.set("name", test_class)
        klasses = Element("classes")
        klasses.append(klass)
        parameter = Element("parameter")
        parameter.set("name", "id")
        parameter.set("value", target)

        inMemoryParameter = Element("parameter")
        inMemoryParameter.set("name", "inMemory")
        inMemoryParameter.set("value", str(in_memory))

        # Add our exclusion group to the test for this target
        groups = Element("groups")
        run = Element("run")
        exclude = Element("exclude")
        exclude.set("name", "disabled")
        run.append(exclude)
        groups.append(run)
        test = Element("test")
        test.set("verbose", "2")
        test.set("name", test_name)
        test.set("annotations", "JDK")
        test.append(parameter)
        test.append(inMemoryParameter)
        test.append(groups)
        test.append(klasses)
        root.append(test)

    # Write TestNG file to disk
    program_dir = os.path.dirname(sys.argv[0])
    testng_file = os.path.join(program_dir, 'testng.xml')
    with open(testng_file, 'w') as xml_file:
        xml_file.write(DOCTYPE)
        ElementTree(root).write(xml_file)
        xml_file.write("\n")
        xml_file.flush()

if __name__ == '__main__':
    try:
        options, args = getopt(sys.argv[1:], "mf:t:", [])
    except GetoptError, (msg, opt):
        usage(msg)

    targets = list()
    thread_count = 1
    test_class = None
    in_memory = False
    for option, argument in options:
        if option == "-f":
            if argument == "-":
                f = sys.stdin
            else:
                f = open(argument)
            targets += f.readlines()
        if option == "-t":
            thread_count = int(argument)
        if option == "-m":
            in_memory = True

    try:
        test_class = args[0]
    except IndexError:
        usage("Expecting test class")
    targets += args[1:]
    if len(targets) == 0:
        usage("Expecting at least one target from file or argument")

    create_testng_xml_file(test_class, targets, thread_count, in_memory)
