#!/usr/bin/python
#
# Test the outcome of a single ATF test case, by running only the test
# program containing it, not the entire test suite.  Likely slower
# than atf_test.py if there are already test results for most source
# dates, and faster otherwise.  Supports qemu and noemu.
#
# Derived from bisect/test-failure-2.py
#

from __future__ import print_function

import anita

import argparse
import os
import re

from bracket import *

def make_test_func(tp, tc, nrepeat = 1):
    def f(ts):
        dist = anita.distribution(anita_dist_url(ts))
        vmm = 'qemu'
        args = anita_args(ts, 'boot')
        print("args", args)
        # XXX this is fragile
        if len(args) >= 2 and args[0:2] == ['--vmm', 'noemu']:
            vmm = 'noemu'
        print('vmm', vmm)
        a = anita.Anita(dist,
                        vmm = vmm,
                        vmm_args = anita_vmm_args(ts, 'boot').split(),
                        workdir = anita_workdir(ts),
                        no_install = True)
        dir, prog = os.path.split(tp)
        a.boot()
        a.login()
        def test_once():
            # Note that we must ignore the exit status of atf-run, because
            # otherwise a failure of some other test cases in the same test
            # program would be misinterpreted as a failure of the one we
            # want.
            status = a.shell_cmd(
                "cd /usr/tests/%s && "
                "{ atf-run %s >log || true; } && "
                "egrep '^tc-end:.* %s, passed' log" % (dir, prog, tc))
            print("shell_cmd returned exit status", status)
            return status == 0
        return all(test_once() for i in range(nrepeat))
    return f

# Parse a test name of the form tp:tc or tp/tc, return a tuple
# XXX dup wrt atf_test.py

def parse_testname(s):
    a = s.split(':')
    if len(a) == 2:
        return tuple(a)
    return tuple(s.rsplit('/', 1))

def op(*args):
    parser = argparse.ArgumentParser()
    parser.add_argument('--repeat', type=int, default=1)
    parser.add_argument('testname')
    opts = parser.parse_args(args)
    tp, tc = parse_testname(opts.testname)
    name = 'atf_single_' + re.sub(r'/', '_', tp) + '_' + tc
    if opts.repeat > 1:
        name += '_repeat_' + str(opts.repeat)
    return TestOp(make_test_func(tp, tc, opts.repeat), [install_op],
                  name = name)
