#!/usr/bin/env python
"""Execute the tests for mason.

The golden test outputs are generated by the script generate_outputs.sh.

You have to give the root paths to the source and the binaries as arguments to
the program.  These are the paths to the directory that contains the 'projects'
directory.

Usage:  run_tests.py SOURCE_ROOT_PATH BINARY_ROOT_PATH
"""
import logging
import os.path
import sys

# Automagically add util/py_lib to PYTHONPATH environment variable.
path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..',
                                    '..', '..', 'util', 'py_lib'))
sys.path.insert(0, path)

import seqan.app_tests as app_tests

def main(source_base, binary_base):
    """Main entry point of the script."""

    print 'Executing test for mason'
    print '========================'
    print
    
    ph = app_tests.TestPathHelper(
        source_base, binary_base,
        'core/apps/mason/tests')  # tests dir

    # ============================================================
    # Auto-detect the binary path.
    # ============================================================

    path_to_program = app_tests.autolocateBinary(
      binary_base, 'core/apps/mason', 'mason')

    # ============================================================
    # Built TestConf list.
    # ============================================================

    # Build list with TestConf objects, analoguely to how the output
    # was generated in generate_outputs.sh.
    conf_list = []

    # We prepare a list of transforms to apply to the output files: Strip the
    # running times from output.
    transforms = [
        app_tests.RegexpReplaceTransform(r'Finished haplotype creation in [^ ]+s',
                                         r'Finished haplotype creation in <cut out>s',
                                         left=True, right=True),
        ]

    # ============================================================
    # Run 454 Reads, Single-End
    # ============================================================

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('454-se-random-N100-nm400-ne40-s0.stdout'),
        args=['454', '-N', '100', '-nm', '400', '-ne', '40', '-s', '0', '-rnp', 'read',
              '-o', ph.outFile('454-se-random-N100-nm400-ne40-s0.fasta'),
              'random.fasta'],
        to_diff=[(ph.inFile('454-se-random-N100-nm400-ne40-s0.fasta'),
                  ph.outFile('454-se-random-N100-nm400-ne40-s0.fasta')),
                 (ph.inFile('454-se-random-N100-nm400-ne40-s0.fasta.sam'),
                  ph.outFile('454-se-random-N100-nm400-ne40-s0.fasta.sam')),
                 (ph.inFile('454-se-random-N100-nm400-ne40-s0.stdout'),
                  ph.outFile('454-se-random-N100-nm400-ne40-s0.stdout'),
                             transforms)])
    conf_list.append(conf)

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('454-se-random-N100-nm400-ne40-s0-sq.stdout'),
        args=['454', '-N', '100', '-nm', '400', '-ne', '40', '-s', '0', '-sq', '-rnp', 'read',
              '-o', ph.outFile('454-se-random-N100-nm400-ne40-s0-sq.fastq'),
              'random.fasta'],
        to_diff=[(ph.inFile('454-se-random-N100-nm400-ne40-s0-sq.fastq'),
                  ph.outFile('454-se-random-N100-nm400-ne40-s0-sq.fastq')),
                 (ph.inFile('454-se-random-N100-nm400-ne40-s0-sq.fastq.sam'),
                  ph.outFile('454-se-random-N100-nm400-ne40-s0-sq.fastq.sam')),
                 (ph.inFile('454-se-random-N100-nm400-ne40-s0-sq.stdout'),
                  ph.outFile('454-se-random-N100-nm400-ne40-s0-sq.stdout'),
                             transforms)])
    conf_list.append(conf)

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('454-se-random-N100-nm200-ne20-s0.stdout'),
        args=['454', '-N', '100', '-nm', '200', '-ne', '20', '-s', '0', '-rnp', 'read',
              '-o', ph.outFile('454-se-random-N100-nm200-ne20-s0.fasta'),
              'random.fasta'],
        to_diff=[(ph.inFile('454-se-random-N100-nm200-ne20-s0.fasta'),
                  ph.outFile('454-se-random-N100-nm200-ne20-s0.fasta')),
                 (ph.inFile('454-se-random-N100-nm200-ne20-s0.fasta.sam'),
                  ph.outFile('454-se-random-N100-nm200-ne20-s0.fasta.sam')),
                 (ph.inFile('454-se-random-N100-nm200-ne20-s0.stdout'),
                  ph.outFile('454-se-random-N100-nm200-ne20-s0.stdout'),
                             transforms)])
    conf_list.append(conf)

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('454-se-random-N100-nm200-ne20-s0-sq.stdout'),
        args=['454', '-N', '100', '-nm', '200', '-ne', '20', '-s', '0', '-sq', '-rnp', 'read',
              '-o', ph.outFile('454-se-random-N100-nm200-ne20-s0-sq.fastq'),
              'random.fasta'],
        to_diff=[(ph.inFile('454-se-random-N100-nm200-ne20-s0-sq.fastq'),
                  ph.outFile('454-se-random-N100-nm200-ne20-s0-sq.fastq')),
                 (ph.inFile('454-se-random-N100-nm200-ne20-s0-sq.fastq.sam'),
                  ph.outFile('454-se-random-N100-nm200-ne20-s0-sq.fastq.sam')),
                 (ph.inFile('454-se-random-N100-nm200-ne20-s0-sq.stdout'),
                  ph.outFile('454-se-random-N100-nm200-ne20-s0-sq.stdout'),
                             transforms)])
    conf_list.append(conf)

    # ============================================================
    # Run Illumina Reads, Single-End
    # ============================================================

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('illumina-se-random-N100-n36-s0.stdout'),
        args=['illumina', '-N', '100', '-n', '36', '-s', '0', '-rnp', 'read',
              '-o', ph.outFile('illumina-se-random-N100-n36-s0.fasta'),
              'random.fasta'],
        to_diff=[(ph.inFile('illumina-se-random-N100-n36-s0.fasta'),
                  ph.outFile('illumina-se-random-N100-n36-s0.fasta')),
                 (ph.inFile('illumina-se-random-N100-n36-s0.fasta.sam'),
                  ph.outFile('illumina-se-random-N100-n36-s0.fasta.sam')),
                 (ph.inFile('illumina-se-random-N100-n36-s0.stdout'),
                  ph.outFile('illumina-se-random-N100-n36-s0.stdout'),
                             transforms)])
    conf_list.append(conf)

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('illumina-se-random-N100-n36-s0-sq.stdout'),
        args=['illumina', '-N', '100', '-n', '36', '-s', '0', '-sq', '-rnp', 'read',
              '-o', ph.outFile('illumina-se-random-N100-n36-s0-sq.fastq'),
              'random.fasta'],
        to_diff=[(ph.inFile('illumina-se-random-N100-n36-s0-sq.fastq'),
                  ph.outFile('illumina-se-random-N100-n36-s0-sq.fastq')),
                 (ph.inFile('illumina-se-random-N100-n36-s0-sq.fastq.sam'),
                  ph.outFile('illumina-se-random-N100-n36-s0-sq.fastq.sam')),
                 (ph.inFile('illumina-se-random-N100-n36-s0-sq.stdout'),
                  ph.outFile('illumina-se-random-N100-n36-s0-sq.stdout'),
                             transforms)])
    conf_list.append(conf)

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('illumina-se-random-N100-n100-s0.stdout'),
        args=['illumina', '-N', '100', '-n', '100', '-s', '0', '-rnp', 'read',
              '-o', ph.outFile('illumina-se-random-N100-n100-s0.fasta'),
              'random.fasta'],
        to_diff=[(ph.inFile('illumina-se-random-N100-n100-s0.fasta'),
                  ph.outFile('illumina-se-random-N100-n100-s0.fasta')),
                 (ph.inFile('illumina-se-random-N100-n100-s0.fasta.sam'),
                  ph.outFile('illumina-se-random-N100-n100-s0.fasta.sam')),
                 (ph.inFile('illumina-se-random-N100-n100-s0.stdout'),
                  ph.outFile('illumina-se-random-N100-n100-s0.stdout'),
                             transforms)])
    conf_list.append(conf)

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('illumina-se-random-N100-n100-s0-sq.stdout'),
        args=['illumina', '-N', '100', '-n', '100', '-s', '0', '-sq', '-rnp', 'read',
              '-o', ph.outFile('illumina-se-random-N100-n100-s0-sq.fastq'),
              'random.fasta'],
        to_diff=[(ph.inFile('illumina-se-random-N100-n100-s0-sq.fastq'),
                  ph.outFile('illumina-se-random-N100-n100-s0-sq.fastq')),
                 (ph.inFile('illumina-se-random-N100-n100-s0-sq.fastq.sam'),
                  ph.outFile('illumina-se-random-N100-n100-s0-sq.fastq.sam')),
                 (ph.inFile('illumina-se-random-N100-n100-s0-sq.stdout'),
                  ph.outFile('illumina-se-random-N100-n100-s0-sq.stdout'),
                             transforms)])
    conf_list.append(conf)

    # ============================================================
    # Run Illumina Reads, Single-End, Existing Contig
    # ============================================================

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('illumina-se-adeno-N100-n36-s0.stdout'),
        args=['illumina', '-N', '100', '-n', '36', '-s', '0', '-rnp', 'read',
              '-o', ph.outFile('illumina-se-adeno-N100-n36-s0.fasta'),
              ph.inFile('adeno-genome.fa')],
        to_diff=[(ph.inFile('illumina-se-adeno-N100-n36-s0.fasta'),
                  ph.outFile('illumina-se-adeno-N100-n36-s0.fasta')),
                 (ph.inFile('illumina-se-adeno-N100-n36-s0.fasta.sam'),
                  ph.outFile('illumina-se-adeno-N100-n36-s0.fasta.sam')),
                 (ph.inFile('illumina-se-adeno-N100-n36-s0.stdout'),
                  ph.outFile('illumina-se-adeno-N100-n36-s0.stdout'),
                             transforms)])
    conf_list.append(conf)

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('illumina-se-adeno-N100-n36-s0-sq.stdout'),
        args=['illumina', '-N', '100', '-n', '36', '-s', '0', '-sq', '-rnp', 'read',
              '-o', ph.outFile('illumina-se-adeno-N100-n36-s0-sq.fastq'),
              ph.inFile('adeno-genome.fa')],
        to_diff=[(ph.inFile('illumina-se-adeno-N100-n36-s0-sq.fastq'),
                  ph.outFile('illumina-se-adeno-N100-n36-s0-sq.fastq')),
                 (ph.inFile('illumina-se-adeno-N100-n36-s0-sq.fastq.sam'),
                  ph.outFile('illumina-se-adeno-N100-n36-s0-sq.fastq.sam')),
                 (ph.inFile('illumina-se-adeno-N100-n36-s0-sq.stdout'),
                  ph.outFile('illumina-se-adeno-N100-n36-s0-sq.stdout'),
                             transforms)])
    conf_list.append(conf)

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('illumina-se-adeno-N100-n100-s0.stdout'),
        args=['illumina', '-N', '100', '-n', '100', '-s', '0', '-rnp', 'read',
              '-o', ph.outFile('illumina-se-adeno-N100-n100-s0.fasta'),
              ph.inFile('adeno-genome.fa')],
        to_diff=[(ph.inFile('illumina-se-adeno-N100-n100-s0.fasta'),
                  ph.outFile('illumina-se-adeno-N100-n100-s0.fasta')),
                 (ph.inFile('illumina-se-adeno-N100-n100-s0.fasta.sam'),
                  ph.outFile('illumina-se-adeno-N100-n100-s0.fasta.sam')),
                 (ph.inFile('illumina-se-adeno-N100-n100-s0.stdout'),
                  ph.outFile('illumina-se-adeno-N100-n100-s0.stdout'),
                             transforms)])
    conf_list.append(conf)

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('illumina-se-adeno-N100-n100-s0-sq.stdout'),
        args=['illumina', '-N', '100', '-n', '100', '-s', '0', '-sq', '-rnp', 'read',
              '-o', ph.outFile('illumina-se-adeno-N100-n100-s0-sq.fastq'),
              ph.inFile('adeno-genome.fa')],
        to_diff=[(ph.inFile('illumina-se-adeno-N100-n100-s0-sq.fastq'),
                  ph.outFile('illumina-se-adeno-N100-n100-s0-sq.fastq')),
                 (ph.inFile('illumina-se-adeno-N100-n100-s0-sq.fastq.sam'),
                  ph.outFile('illumina-se-adeno-N100-n100-s0-sq.fastq.sam')),
                 (ph.inFile('illumina-se-adeno-N100-n100-s0-sq.stdout'),
                  ph.outFile('illumina-se-adeno-N100-n100-s0-sq.stdout'),
                             transforms)])
    conf_list.append(conf)

    # ============================================================
    # Run Illumina Reads, Paired-End
    # ============================================================

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('illumina-pe-random-N100-n36-s0.stdout'),
        args=['illumina', '-mp', '-N', '100', '-n', '36', '-s', '0', '-rnp', 'read',
              '-o', ph.outFile('illumina-pe-random-N100-n36-s0.fasta'),
              'random.fasta'],
        to_diff=[(ph.inFile('illumina-pe-random-N100-n36-s0_1.fasta'),
                  ph.outFile('illumina-pe-random-N100-n36-s0_1.fasta')),
                 (ph.inFile('illumina-pe-random-N100-n36-s0_2.fasta'),
                  ph.outFile('illumina-pe-random-N100-n36-s0_2.fasta')),
                 (ph.inFile('illumina-pe-random-N100-n36-s0.fasta.sam'),
                  ph.outFile('illumina-pe-random-N100-n36-s0.fasta.sam')),
                 (ph.inFile('illumina-pe-random-N100-n36-s0.stdout'),
                  ph.outFile('illumina-pe-random-N100-n36-s0.stdout'),
                             transforms)])
    conf_list.append(conf)

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('illumina-pe-random-N100-n36-s0-sq.stdout'),
        args=['illumina', '-mp', '-N', '100', '-n', '36', '-s', '0', '-sq', '-rnp', 'read',
              '-o', ph.outFile('illumina-pe-random-N100-n36-s0-sq.fastq'),
              'random.fasta'],
        to_diff=[(ph.inFile('illumina-pe-random-N100-n36-s0-sq_1.fastq'),
                  ph.outFile('illumina-pe-random-N100-n36-s0-sq_1.fastq')),
                 (ph.inFile('illumina-pe-random-N100-n36-s0-sq_2.fastq'),
                  ph.outFile('illumina-pe-random-N100-n36-s0-sq_2.fastq')),
                 (ph.inFile('illumina-pe-random-N100-n36-s0-sq.fastq.sam'),
                  ph.outFile('illumina-pe-random-N100-n36-s0-sq.fastq.sam')),
                 (ph.inFile('illumina-pe-random-N100-n36-s0-sq.stdout'),
                  ph.outFile('illumina-pe-random-N100-n36-s0-sq.stdout'),
                             transforms)])
    conf_list.append(conf)

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('illumina-pe-random-N100-n100-s0.stdout'),
        args=['illumina', '-mp', '-N', '100', '-n', '100', '-s', '0', '-rnp', 'read',
              '-o', ph.outFile('illumina-pe-random-N100-n100-s0.fasta'),
              'random.fasta'],
        to_diff=[(ph.inFile('illumina-pe-random-N100-n100-s0_1.fasta'),
                  ph.outFile('illumina-pe-random-N100-n100-s0_1.fasta')),
                 (ph.inFile('illumina-pe-random-N100-n100-s0_2.fasta'),
                  ph.outFile('illumina-pe-random-N100-n100-s0_2.fasta')),
                 (ph.inFile('illumina-pe-random-N100-n100-s0.fasta.sam'),
                  ph.outFile('illumina-pe-random-N100-n100-s0.fasta.sam')),
                 (ph.inFile('illumina-pe-random-N100-n100-s0.stdout'),
                  ph.outFile('illumina-pe-random-N100-n100-s0.stdout'),
                             transforms)])
    conf_list.append(conf)

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('illumina-pe-random-N100-n100-s0-sq.stdout'),
        args=['illumina', '-mp', '-N', '100', '-n', '100', '-s', '0', '-sq', '-rnp', 'read',
              '-o', ph.outFile('illumina-pe-random-N100-n100-s0-sq.fastq'),
              'random.fasta'],
        to_diff=[(ph.inFile('illumina-pe-random-N100-n100-s0-sq_1.fastq'),
                  ph.outFile('illumina-pe-random-N100-n100-s0-sq_1.fastq')),
                 (ph.inFile('illumina-pe-random-N100-n100-s0-sq_2.fastq'),
                  ph.outFile('illumina-pe-random-N100-n100-s0-sq_2.fastq')),
                 (ph.inFile('illumina-pe-random-N100-n100-s0-sq.fastq.sam'),
                  ph.outFile('illumina-pe-random-N100-n100-s0-sq.fastq.sam')),
                 (ph.inFile('illumina-pe-random-N100-n100-s0-sq.stdout'),
                  ph.outFile('illumina-pe-random-N100-n100-s0-sq.stdout'),
                             transforms)])
    conf_list.append(conf)

    # ============================================================
    # Run Sanger Reads, Single-End
    # ============================================================

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('sanger-se-random-N100-nm400-ne40-s0.stdout'),
        args=['sanger', '-N', '100', '-nm', '400', '-ne', '40', '-s', '0', '-rnp', 'read',
              '-o', ph.outFile('sanger-se-random-N100-nm400-ne40-s0.fasta'),
              'random.fasta'],
        to_diff=[(ph.inFile('sanger-se-random-N100-nm400-ne40-s0.fasta'),
                  ph.outFile('sanger-se-random-N100-nm400-ne40-s0.fasta')),
                 (ph.inFile('sanger-se-random-N100-nm400-ne40-s0.fasta.sam'),
                  ph.outFile('sanger-se-random-N100-nm400-ne40-s0.fasta.sam')),
                 (ph.inFile('sanger-se-random-N100-nm400-ne40-s0.stdout'),
                  ph.outFile('sanger-se-random-N100-nm400-ne40-s0.stdout'),
                             transforms)])
    conf_list.append(conf)

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('sanger-se-random-N100-nm400-ne40-s0-sq.stdout'),
        args=['sanger', '-N', '100', '-nm', '400', '-ne', '40', '-s', '0', '-sq', '-rnp', 'read',
              '-o', ph.outFile('sanger-se-random-N100-nm400-ne40-s0-sq.fastq'),
              'random.fasta'],
        to_diff=[(ph.inFile('sanger-se-random-N100-nm400-ne40-s0-sq.fastq'),
                  ph.outFile('sanger-se-random-N100-nm400-ne40-s0-sq.fastq')),
                 (ph.inFile('sanger-se-random-N100-nm400-ne40-s0-sq.fastq.sam'),
                  ph.outFile('sanger-se-random-N100-nm400-ne40-s0-sq.fastq.sam')),
                 (ph.inFile('sanger-se-random-N100-nm400-ne40-s0-sq.stdout'),
                  ph.outFile('sanger-se-random-N100-nm400-ne40-s0-sq.stdout'),
                             transforms)])
    conf_list.append(conf)

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('sanger-se-random-N100-nm200-ne20-s0.stdout'),
        args=['sanger', '-N', '100', '-nm', '200', '-ne', '20', '-s', '0', '-rnp', 'read',
              '-o', ph.outFile('sanger-se-random-N100-nm200-ne20-s0.fasta'),
              'random.fasta'],
        to_diff=[(ph.inFile('sanger-se-random-N100-nm200-ne20-s0.fasta'),
                  ph.outFile('sanger-se-random-N100-nm200-ne20-s0.fasta')),
                 (ph.inFile('sanger-se-random-N100-nm200-ne20-s0.fasta.sam'),
                  ph.outFile('sanger-se-random-N100-nm200-ne20-s0.fasta.sam')),
                 (ph.inFile('sanger-se-random-N100-nm200-ne20-s0.stdout'),
                  ph.outFile('sanger-se-random-N100-nm200-ne20-s0.stdout'),
                             transforms)])
    conf_list.append(conf)

    conf = app_tests.TestConf(
        program=path_to_program,
        redir_stdout=ph.outFile('sanger-se-random-N100-nm200-ne20-s0-sq.stdout'),
        args=['sanger', '-N', '100', '-nm', '200', '-ne', '20', '-s', '0', '-sq', '-rnp', 'read',
              '-o', ph.outFile('sanger-se-random-N100-nm200-ne20-s0-sq.fastq'),
              'random.fasta'],
        to_diff=[(ph.inFile('sanger-se-random-N100-nm200-ne20-s0-sq.fastq'),
                  ph.outFile('sanger-se-random-N100-nm200-ne20-s0-sq.fastq')),
                 (ph.inFile('sanger-se-random-N100-nm200-ne20-s0-sq.fastq.sam'),
                  ph.outFile('sanger-se-random-N100-nm200-ne20-s0-sq.fastq.sam')),
                 (ph.inFile('sanger-se-random-N100-nm200-ne20-s0-sq.stdout'),
                  ph.outFile('sanger-se-random-N100-nm200-ne20-s0-sq.stdout'),
                             transforms)])
    conf_list.append(conf)

    # Execute the tests.
    failures = 0
    for conf in conf_list:
        print ' '.join(['mason'] + conf.args),
        sys.stdout.flush()
        res = app_tests.runTest(conf)
        # Output to the user.
        print ' '.join(['mason'] + conf.args),
        if res:
             print 'OK'
        else:
            failures += 1
            print 'FAILED'

    # Cleanup.
    ph.deleteTempDir()

    print '=============================='
    print '     total tests: %d' % len(conf_list)
    print '    failed tests: %d' % failures
    print 'successful tests: %d' % (len(conf_list) - failures)
    print '=============================='
    # Compute and return return code.
    return failures != 0


if __name__ == '__main__':
    sys.exit(app_tests.main(main))
