# Test building a NetBSD release.  Used for evauluating the
# performance of the build host.
#
# This does not use make_sh_test_op because that did not yet work
# with noemu when the test was written.
#
# The build log is directed to a file and only the last 1000 lines
# shown, because otherwise the build speed is limited by the serial
# console when running under noemu.

# XXX hardcoded local mirror URL
# XXX hardcoded disk device names

import argparse
import sys

from bracket import *

assert(sys.version_info[0] >= 3) # nonlocal

def make_test_func(name, release,
                   tmpdir = False, tmpfs = False, async_mount = False,
                   mfs = False, no_xz = False, lockstat = False,
                   jobtoken = False):
    def test_func(ts):
        build_sh_flags = ''
        if tmpdir:
            build_sh_flags += '-V TMPDIR=/tmp '
        if no_xz:
            build_sh_flags += '-V USE_XZ_SETS=no '
        logfn = os.path.join(results_dir(ts), name + ".log")
        slogfn = os.path.join(results_dir(ts), name + ".slog")
        # Note that the lockstat output needs to go on a persistent
        # disk, not tmpfs, so that it can be retrieved
        lockstat_prefix = ["", "lockstat -b 999999 -o /root/lockstat.out "][lockstat]
        return anita_run_1(ts, "boot",
                logfn,
                # Note that we can't use /usr/src, because if the
                # source sets were installed, it already contains a source
                # tree of the host version.  Instead, we put the sources
                # in /b/usr/src.
                # Also note that we don't build X.
                extra_anita_args = [
                    "--run", "set -ex; " +
                        # Time for media autonegotiation and DAD
                        "sleep 60; " +
                        "mkdir -p /b && " +
                        ["", "mount -t tmpfs tmpfs /b && "][tmpfs] +
                        ["", "mount -o async /dev/dk2 /b && "][async_mount] +
                        ["", "mount_mfs -s 32g swap /b && "][mfs] +
                        "rm -rf /b/* && " +
                        "mkdir /b/obj && " +
                        "cd /root && for f in gnusrc sharesrc src syssrc; " +
                        "do ftp http://mirror.araneus.fi/ftp.netbsd.org/pub/NetBSD/NetBSD-%s/source/sets/$f.tgz && " % release +
                        "zcat $f.tgz | " +
                        "(cd /b && tar xf -); done && " +
                        ["", "cd /b/usr && ftp http://mirror.araneus.fi/local/make-jobtoken.patch && patch <make-jobtoken.patch && "][jobtoken] + 
                        "cd /b/usr/src && " +
                        "if time %s" % lockstat_prefix +
                        "sh build.sh -O /b/obj -j $(sysctl -n hw.ncpuonline) %s release >build.log 2>&1; " % build_sh_flags +
                        "then status=0; else status=1; fi; " +
                        "tail -n 1000 build.log; test $status = 0",
                    "--run-timeout", "14400",
                    "--no-install"
                ])
    return test_func

def op(*args):
    parser = argparse.ArgumentParser()

    all_flags = []

    # Define a boolean flag argument
    def flag_opt(optname, help):
        nonlocal all_flags
        parser.add_argument('--' + optname, action='store_true', help=help)
        all_flags.append(re.sub('-', '_', optname))

    flag_opt('tmpdir', 'use -V TMPDIR=/tmp')
    flag_opt('tmpfs', 'build on tmpfs')
    flag_opt('async-mount', 'build on async-mounted disk')
    flag_opt('mfs', 'build on mfs')
    # --no-xz makes no difference in -8, but will in -9
    flag_opt('no-xz', 'don\'t use xz compression for the sets')
    flag_opt('lockstat', 'run build.sh under lockstat')
    flag_opt('jobtoken', 'patch make(1) with job token bug fix')

    parser.add_argument('release', type=str)

    opts = parser.parse_args(args)
    
    name = 'build_release_' + re.sub(r'\.', '_', opts.release)

    # Qualify the test name with the flags
    for flag in all_flags:
        if getattr(opts, flag):
            name += '_' + flag

    # Note conversion of namespace to dict using vars()
    return TestOp(make_test_func(name, **vars(opts)),
                  [install_op], name = name)
