# Run a test repeatedly, succeeding iff it succeeds every time.
# Useful for bisecting tests that fail only randomly.
#
# If the option --any-pass is give, the repeated test succeeds if any
# iteration passes.  Otherwise (the default), the repeated test
# succeds if every iteration passes.

from __future__ import print_function

import argparse
import os

from bracket import test_args2op, TestOp, force, rerun, db_put, results_dir
from utils import read_file, append_to_file

def make_test_func(inner_op, nrepeat, name, pred):
    def f(ts):
        full_log_fn = os.path.join(results_dir(ts), name + ".log")
        def test_once(i):
            r = rerun(inner_op, ts)
            print("iteration %d result:" % i, r)
            # Consolidate logs
            try:
                iter_log_fn = os.path.join(results_dir(ts), inner_op.name + ".log")
                iter_log = read_file(iter_log_fn)
                title = b"\n--- iteration %d ---\n\n" % i
                append_to_file(full_log_fn, title + iter_log)
            except Exception as e:
                print("could not append log:", str(e))
            return r
        # return all(test_once(i) for i in range(nrepeat))
        npassed = sum(test_once(i) for i in range(nrepeat))
        db_put(ts, name + '_npassed', str(npassed))
        return pred(npassed)
    return f

# Parse a test name of the form tp:tc or tp/tc, return a tuple

def op(*args):
    parser = argparse.ArgumentParser()
    parser.add_argument('--any-pass', action='store_true')
    parser.add_argument('nrepeat', type=int)
    parser.add_argument('inner', nargs='*')
    opts = parser.parse_args(args)
    nrepeat = opts.nrepeat
    if opts.any_pass:
        def pred(npassed):
            return npassed > 0
        suffix = '_anypassed'
    else:
        def pred(npassed):
            return npassed == nrepeat
        suffix = ''
    inner_op = test_args2op(opts.inner)
    name = inner_op.name + '_repeat' + suffix + '_' + str(nrepeat)
    return TestOp(make_test_func(inner_op, nrepeat, name, pred), [], name = name)
