#!/usr/bin/python
#
# Test if the ddb trace command stopped working altogether
# (as opposed to the usual fubar state of working about half the time).
#
# See http://gnats.netbsd.org/44260
#

from __future__ import print_function

import pexpect
import random
import sys
import time

import anita

from bracket import *

n_par = 10
n_ser = 100
n_tot = n_par * n_ser

use_current_repository()

# Delay for a random amount of time.
# This takes up to a second or two on a 2.4 GHz Intel Core 2.
# We busy wait rather than sleep because we get a far higher
# resolution this way, and don't end up synchronized with the
# clock tick, which is the whole point of the delay, really.

def random_delay():
    random.seed()
    niter = random.randint(5000000, 20000000)
    print("random delay: %d iterations" % niter)
    for i in range(niter):
        pass

def test_ddb_bt(ts):
    dist = anita.URL(anita_dist_url(ts))
    # vmm_args = ['--no-kvm']
    a = anita.Anita(dist, vmm_args = [], workdir = anita_workdir(ts), memory_size = '128M')
    child = a.boot()
    a.shell_cmd("sysctl -w ddb.lines=0")
    nsuccess = 0
    for j in range(n_ser):
        random_delay()
        # send a break
        child.send("\001b")
        child.expect("db{")
        child.send("bt\n");
        try:
            child.expect("(main)|(idle)", 5);
        except:
            pass
        else:
            nsuccess += 1
            time.sleep(1)
        child.send("cont\n");       
    print("nsuccess =", nsuccess)
    return 10 + nsuccess

def test_ddb_bt_multi(ts):
    nsuccess = 0
    for i in range(n_par):
        pid = os.fork()
        if (pid == 0):
            # child
            logfn = os.path.join(test_dir(ts), "p%i.log" % i)
            print("logging to", logfn);
            f = open(logfn, "w")
            sys.stdout = f
            sys.stderr = f
            # Return the number of successes as exit status
            sys.exit(test_ddb_bt(ts))

    for i in range(n_par):
        pid, val = os.wait()
        signal = val & 0xFF
        status = val >> 8
        print("pid", pid, "signal", signal, "status", status)
        if status >= 10:
            p_nsuccess = status - 10
        else:
            p_nsuccess = 0
        nsuccess += p_nsuccess

    cache_status(ts, "ddb_bt_idle_%i_test_nsuccess" % n_tot, nsuccess)
    return nsuccess != 0

def op():
    return TestOp(test_ddb_bt_multi, [install_op], name = "ddb_bt_idle_%i_test" % n_tot)
