Example #1
0
 def __init__(self, binary):
     self.binary = binary
     self.o = bs.Options()
     self.pm = bs.ProjectMap()
     self.blacklist_txt = None
     self.version = None
     bd = self.pm.project_build_dir()
     hw_prefix = self.o.hardware[:3]
     if self.o.hardware == "g965":
         hw_prefix = self.o.hardware
     # Note: bsw has known failures that need to be resolved
     # first: https://bugs.freedesktop.org/show_bug.cgi?id=104981
     if hw_prefix in ['g33', 'g45', 'ilk', 'g965', 'hsw', 'byt', 'bsw']:
         raise Exception(("ERROR: This platform is not supported by "
                          "this test"))
     if "gles2" in self.binary:
         self.blacklist_txt = (bd + hw_prefix +
                               "_expectations/gles2_unstable_tests.txt")
     if "gles3" in self.binary:
         self.blacklist_txt = (bd + hw_prefix +
                               "_expectations/gles3_unstable_tests.txt")
     if "gles31" in self.binary:
         self.blacklist_txt = (bd + hw_prefix +
                               "_expectations/gles31_unstable_tests.txt")
     if "egl" in self.binary:
         self.blacklist_txt = (bd + hw_prefix +
                               "_expectations/egl_unstable_tests.txt")
Example #2
0
    def __init__(self):
        global_opts = bs.Options()

        options = []
        options = options + [
            "--enable-gbm",
            "--with-egl-platforms=x11,drm",
            "--enable-glx-tls",
            "--enable-gles1",
            "--enable-gles2",
            "--with-dri-drivers=i965,swrast,i915",

            # disable video drivers:
            # bbe6f7f865cd4316b5f885507ee0b128a20686eb
            # caused build failure unrelated to intel mesa
            # team.
            "--disable-xvmc",
            "--disable-vdpau",

            # gallium tested with mesa-buildtest
            "--without-gallium-drivers"
        ]
        if os.path.exists(bs.ProjectMap().project_source_dir() +
                          "/src/intel/vulkan"):
            options.append("--with-vulkan-drivers=intel")

        if global_opts.config == 'debug':
            options.append('--enable-debug')

        # always enable optimizations in mesa because tests are too slow
        # without them.
        bs.AutoBuilder.__init__(self,
                                configure_options=options,
                                opt_flags="-O2")
Example #3
0
    def __init__(self):
        o = bs.Options()
        pm = bs.ProjectMap()
        self.build_root = pm.build_root()
        libdir = "x86_64-linux-gnu"
        self.version = None
        if o.arch == "m32":
            libdir = "i386-linux-gnu"
        self.env = { "LD_LIBRARY_PATH" : self.build_root + "/lib:" + \
                     self.build_root + "/lib/" + libdir + ":" + self.build_root + "/lib/dri",
                     "LIBGL_DRIVERS_PATH" : self.build_root + "/lib/dri",
                     "GBM_DRIVERS_PATH" : self.build_root + "/lib/dri",
                     # fixes dxt subimage tests that fail due to a
                     # combination of unreasonable tolerances and possibly
                     # bugs in debian's s2tc library.  Recommended by nroberts
                     "S2TC_DITHER_MODE" : "NONE",

                     # without this, Xorg limits frame rate to 1 FPS
                     # when display sleeps, cratering tests execution
                     "vblank_mode": "0"
        }

        self.env["MESA_GL_VERSION_OVERRIDE"] = "4.5"
        self.env["MESA_GLSL_VERSION_OVERRIDE"] = "450"
        o.update_env(self.env)
Example #4
0
 def __init__(self, extra_definitions=None, compiler="gcc"):
     bs.CMakeBuilder.__init__(self,
                              extra_definitions=extra_definitions,
                              compiler=compiler,
                              install=False)
     self._o = bs.Options()
     self._pm = bs.ProjectMap()
Example #5
0
def main():
    global_opts = bs.Options()

    options = []
    if global_opts.arch == "m32":
        # m32 build not supported
        return

    options = options + [
        "--enable-gbm", "--enable-llvm", "--with-egl-platforms=x11,drm",
        "--enable-glx-tls", "--enable-gles1", "--enable-gles2",
        "--with-gallium-drivers=svga,swrast,r300,r600,radeonsi,nouveau",
        "--with-vulkan-drivers=intel,radeon"
    ]

    if global_opts.config == 'debug':
        options.append('--enable-debug')

    # builder = bs.AutoBuilder(configure_options=options, export=False)
    builder = NoTest(configure_options=options)

    save_dir = os.getcwd()
    try:
        bs.build(builder)
    except subprocess.CalledProcessError as e:
        # build may have taken us to a place where ProjectMap doesn't work
        os.chdir(save_dir)
        bs.Export().create_failing_test("mesa-buildtest", str(e))
Example #6
0
    def __init__(self):
        self.opts = bs.Options()

        if self.opts.config == 'debug':
            print "ERROR: perf not supported for debug"
            assert (False)

        pm = bs.ProjectMap()
        self._src_dir = pm.project_source_dir("mesa")
        self._build_dir = "/tmp/mesa-perf/build_" + self.opts.arch

        # generated with `gcc -E -v -march=native - < /dev/null 2>&1 | grep cc1`
        self._flags = [
            '-march=silvermont', '-mmmx', '-mno-3dnow', '-msse', '-msse2',
            '-msse3', '-mssse3', '-mno-sse4a', '-mcx16', '-msahf', '-mmovbe',
            '-maes', '-msha', '-mpclmul', '-mpopcnt', '-mno-abm', '-mno-lwp',
            '-mno-fma', '-mno-fma4', '-mno-xop', '-mno-bmi', '-mno-bmi2',
            '-mno-tbm', '-mno-avx', '-mno-avx2', '-msse4.2', '-msse4.1',
            '-mno-lzcnt', '-mno-rtm', '-mno-hle', '-mrdrnd', '-mno-f16c',
            '-mfsgsbase', '-mrdseed', '-mprfchw', '-mno-adx', '-mfxsr',
            '-mno-xsave', '-mno-xsaveopt', '-mno-avx512f', '-mno-avx512er',
            '-mno-avx512cd', '-mno-avx512pf', '-mno-prefetchwt1',
            '-mclflushopt', '-mno-xsavec', '-mno-xsaves', '-mno-avx512dq',
            '-mno-avx512bw', '-mno-avx512vl', '-mno-avx512ifma',
            '-mno-avx512vbmi', '-mno-clwb', '-mno-mwaitx', '-mno-clzero',
            '-mno-pku', '--param', 'l1-cache-size=24', '--param',
            'l1-cache-line-size=64', '--param', 'l2-cache-size=1024',
            '-mtune=generic'
        ]
Example #7
0
 def blacklist(self, all_tests):
     # filter tests for the platform
     o = bs.Options()
     blacklist_file = self.pm.project_build_dir(
     ) + o.hardware[:3] + "_expectations/vk_unstable_tests.txt"
     blacklist = bs.DeqpTrie()
     blacklist.add_txt(blacklist_file)
     all_tests.filter(blacklist)
Example #8
0
def test_build_info():
    t = tempfile.mkdtemp()
    args= ["ignore_arg0", "--result_path", t]
    o = bs.Options(args)
    pi = bs.ProjectInvoke(o, project="mesa")
    pi.set_info("status", "done")
    assert(pi.get_info("status") == "done")
    shutil.rmtree(t)
Example #9
0
    def __init__(self):
        self.o = bs.Options()
        self.pm = bs.ProjectMap()

        self.env = {"MESA_GLES_VERSION_OVERRIDE" : ""}
        if self._gles_32():
            self.env["MESA_GLES_VERSION_OVERRIDE"] = "3.2"
        elif self._gles_31():
            self.env["MESA_GLES_VERSION_OVERRIDE"] = "3.1"
Example #10
0
def meson_build():
    global_opts = bs.Options()

    options = [
        '-Detnaviv=true',
        '-Dfreedreno=true',
    ]
    if global_opts.config != 'debug':
        options.extend(['-Dbuildtype=release', '-Db_ndebug=true'])
    b = bs.builders.MesonBuilder(extra_definitions=options, install=True)
    bs.build(b)
Example #11
0
 def test(self):
     pm = bs.ProjectMap()
     global_opts = bs.Options()
     if global_opts.arch == "m64":
         icd_name = "intel_icd.x86_64.json"
     elif global_opts.arch == "m32":
         icd_name = "intel_icd.i686.json"
     env = {"VK_ICD_FILENAMES" : pm.build_root() + \
            "/share/vulkan/icd.d/" + icd_name,
            "ANV_ABORT_ON_DEVICE_LOSS" : "true"}
     tester = bs.DeqpTester()
     binary = pm.build_root() + "/opt/deqp/modules/vulkan/deqp-vk"
     results = tester.test(binary,
                           VulkanTestList(), ["--deqp-surface-type=fbo"],
                           env=env)
     o = bs.Options()
     config = bs.get_conf_file(o.hardware,
                               o.arch,
                               project=pm.current_project())
     tester.generate_results(results, bs.ConfigFilter(config, o))
Example #12
0
 def blacklist(self, all_tests):
     # filter tests for the platform
     o = bs.Options()
     blacklist_file = self.pm.project_build_dir(
     ) + o.hardware[:3] + "_expectations/vk_unstable_tests.txt"
     if "glk" in o.hardware:
         blacklist_file = self.pm.project_source_dir(
             "prerelease"
         ) + "/vulkancts-test/glk_expectations/vk_unstable_tests.txt"
     blacklist = bs.DeqpTrie()
     blacklist.add_txt(blacklist_file)
     all_tests.filter(blacklist)
Example #13
0
 def test(self):
     mv = bs.mesa_version()
     if "17.2" in mv or "17.1" in mv:
         return
     t = bs.DeqpTester()
     results = t.test(self.pm.build_root() + "/bin/es/modules/glcts",
                      GLESCTSList(),
                      env={"MESA_GLES_VERSION_OVERRIDE": "3.2"})
     o = bs.Options()
     config = bs.get_conf_file(self.o.hardware,
                               self.o.arch,
                               project=self.pm.current_project())
     t.generate_results(results, bs.ConfigFilter(config, o))
Example #14
0
    def test(self):
        mv = bs.mesa_version()
        if "17.2" in mv or "17.1" in mv:
            print("NOTICE: GLCTS will NOT be run since the system has Mesa version <17.3")
            return
        t = bs.DeqpTester()
        results = t.test(self.pm.build_root() + "/bin/gl/modules/glcts",
                         GLCTSList(),
                         env = {"MESA_GL_VERSION_OVERRIDE" : "4.6",
                                "MESA_GLSL_VERSION_OVERRIDE" : "460"})

        o = bs.Options()
        config = bs.get_conf_file(self.o.hardware, self.o.arch, project=self.pm.current_project())
        t.generate_results(results, bs.ConfigFilter(config, o))
Example #15
0
    def build(self):
        save_dir = os.getcwd()
        os.chdir(self.src_dir)

        # scons build is broken, will occasionally fail if temporaries
        # are still around.  Use git's nuclear clean method instead of
        # the clean targets.
        bs.run_batch_command(["git", "clean", "-dfx"])

        env = {}
        bs.Options().update_env(env)
        bs.run_batch_command(["scons", "-j", str(bs.cpu_count())], env=env)

        bs.run_batch_command(["git", "clean", "-dfx"])
        os.chdir(save_dir)
Example #16
0
def test_dep_graph():
    #pytest.set_trace()
    args = ["ignore_arg0", "--action=build,test", "--config=debug"]
    o = bs.Options(args)
    g = bs.DependencyGraph("all-test", o)
    ready_builds = g.ready_builds()
    assert (ready_builds)
    built = []
    loop_count = 0
    while ready_builds:
        loop_count += 1
        for bi in g.ready_builds():
            assert str(bi) not in built
            built.append(str(bi))
            g.build_complete(bi)
        ready_builds = g.ready_builds()
    assert (loop_count > 2)
Example #17
0
 def __init__(self, binary):
     self.binary = binary
     self.o = bs.Options()
     self.pm = bs.ProjectMap()
     self.blacklist_txt = None
     self.version = None
     bd = self.pm.project_build_dir()
     hw_prefix = self.o.hardware[:3]
     if self.o.hardware == "g965":
         hw_prefix = self.o.hardware
     if "gles2" in self.binary:
         self.blacklist_txt = bd + hw_prefix + "_expectations/gles2_unstable_tests.txt"
     if "gles3" in self.binary:
         self.blacklist_txt = bd + hw_prefix + "_expectations/gles3_unstable_tests.txt"
     if "gles31" in self.binary:
         self.blacklist_txt = bd + hw_prefix + "_expectations/gles31_unstable_tests.txt"
     if "egl" in self.binary:
         self.blacklist_txt = bd + hw_prefix + "_expectations/egl_unstable_tests.txt"
Example #18
0
 def __init__(self, binary, cts_tests):
     self.binary = binary
     self.o = bs.Options()
     self.pm = bs.ProjectMap()
     self.blacklist_txt = None
     self.cts_blacklist = cts_tests
     self.version = None
     bd = self.pm.project_build_dir()
     if "glk" in self.o.hardware:
         bd = self.pm.project_source_dir("prerelease") + "/deqp-test/"
     if "gles2" in self.binary:
         self.blacklist_txt = bd + self.o.hardware[:3] + "_expectations/gles2_unstable_tests.txt"
     if "gles3" in self.binary:
         self.blacklist_txt = bd + self.o.hardware[:3] + "_expectations/gles3_unstable_tests.txt"
     if "gles31" in self.binary:
         self.blacklist_txt = bd + self.o.hardware[:3] + "_expectations/gles31_unstable_tests.txt"
     if "egl" in self.binary:
         self.blacklist_txt = bd + self.o.hardware[:3] + "_expectations/egl_unstable_tests.txt"
Example #19
0
def meson_build():
    global_opts = bs.Options()

    options = [
        '-Dgallium-drivers=',
        '-Ddri-drivers=i965,i915',
        '-Dvulkan-drivers=intel',
        '-Dplatforms=x11,drm',
    ]

    cpp_args = None
    if global_opts.config == 'debug':
        cpp_args = "-DDEBUG"
    else:
        options.extend(['-Dbuildtype=release', '-Db_ndebug=true'])
    b = bs.builders.MesonBuilder(extra_definitions=options,
                                 install=True,
                                 cpp_args=cpp_args)
    bs.build(b)
Example #20
0
    def test(self):
        t = bs.DeqpTester()
        version = bs.mesa_version()
        if "bxt" in self.o.hardware:
            if "13.0" in version:
                # unsupported platforms
                return
        if "glk" in self.o.hardware:
            if "17.0" in version:
                # unsupported platforms
                return

        results = t.test(self.pm.build_root() + "/bin/es/cts/glcts",
                         bs.CtsTestList(),
                         [],
                         self.env)

        o = bs.Options()
        config = bs.get_conf_file(self.o.hardware, self.o.arch, project=self.pm.current_project())
        t.generate_results(results, bs.ConfigFilter(config, o))
Example #21
0
def post_process_results(xml):
    t = ET.parse(xml)
    o = bs.Options()
    conf = None
    try:
        conf = bs.get_conf_file(o.hardware, o.arch, project="crucible-test")
    except bs.NoConfigFile:
        pass
    if conf:
        # key=name, value=status
        expected_status = {}
        c = ConfigParser.SafeConfigParser(allow_no_value=True)
        c.read(conf)
        for section in c.sections():
            for (test, _) in c.items(section):
                if test in expected_status:
                    raise Exception("test has multiple entries: " + test)
                expected_status[test] = section
        for atest in t.findall(".//testcase"):
            if atest.attrib["name"] not in expected_status:
                continue
            if atest.attrib["status"] == "lost":
                atest.attrib["status"] = "crash"

            expected = expected_status[atest.attrib["name"]]
            if expected == "expected-failures":
                # change fail to pass
                if atest.attrib["status"] == "fail":
                    for ftag in atest.findall("failure"):
                        atest.remove(ftag)
                    so = ET.Element("system-out")
                    so.text = "Passing test as an expected failure"
                    atest.append(so)
                elif atest.attrib["status"] == "crash":
                    atest.append(ET.Element("failure"))
                    so = ET.Element("system-out")
                    so.text = "ERROR: this test crashed when it expected failure"
                    atest.append(so)
                elif atest.attrib["status"] == "pass":
                    atest.append(ET.Element("failure"))
                    so = ET.Element("system-out")
                    so.text = "ERROR: this test passed when it expected failure"
                    atest.append(so)
                elif atest.attrib["status"] == "skip":
                    atest.append(ET.Element("failure"))
                    so = ET.Element("system-out")
                    so.text = "ERROR: this test skipped when it expected failure"
                    atest.append(so)
                else:
                    raise Exception("test has unknown status: " +
                                    atest.attrib["name"] + " " +
                                    atest.attrib["status"])
            elif expected == "expected-crashes":
                # change error to pass
                if atest.attrib["status"] == "crash":
                    for ftag in atest.findall("error"):
                        atest.remove(ftag)
                    so = ET.Element("system-out")
                    so.text = "Passing test as an expected crash"
                    atest.append(so)
                elif atest.attrib["status"] == "fail":
                    atest.append(ET.Element("failure"))
                    so = ET.Element("system-out")
                    so.text = "ERROR: this test failed when it expected crash"
                    atest.append(so)
                elif atest.attrib["status"] == "pass":
                    atest.append(ET.Element("failure"))
                    so = ET.Element("system-out")
                    so.text = "ERROR: this test passed when it expected crash"
                    atest.append(so)
                elif atest.attrib["status"] == "skip":
                    atest.append(ET.Element("failure"))
                    so = ET.Element("system-out")
                    so.text = "ERROR: this test skipped when it expected crash"
                    atest.append(so)
                else:
                    raise Exception("test has unknown status: " +
                                    atest.attrib["name"] + " " +
                                    atest.attrib["status"])

    for atest in t.findall(".//testcase"):
        atest.attrib["name"] = atest.attrib["name"] + "." + o.hardware + o.arch
    t.write(xml)
Example #22
0
#!/usr/bin/python

import os
import sys
import urllib2

sys.path.append(
    os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), ".."))
import build_support as bs

# Leeroy runs the builds inside of a user namespace, so it can bind
# mount on /tmp.  This prevents the use of sudo.  This build just
# triggers the "single_reboot" job, which does not run in a user
# namespace.

server = bs.ProjectMap().build_spec().find("build_master").attrib["host"]
url = "http://" + server + "/job/reboot_single/buildWithParameters?token=noauth&label=" + bs.Options(
).hardware
print "opening: " + url
urllib2.urlopen(url)
Example #23
0
                except:
                    continue
                repo_path = self._src_dir + "/external/" + package.baseDir + "/src/"
                print "Cleaning: " + repo_path + " : " + package.revision
                savedir = os.getcwd()
                os.chdir(repo_path)
                bs.run_batch_command(["git", "clean", "-xfd"])
                bs.run_batch_command(["git", "reset", "--hard", "HEAD"])
                os.chdir(savedir)
                print "Checking out: " + repo_path + " : " + package.revision
                repo = git.Repo(repo_path)
                repo.git.checkout(package.revision, force=True)

        bs.CMakeBuilder.build(self)
        dest = self._pm.build_root() + "/opt/deqp/"
        if not os.path.exists(dest):
            os.makedirs(dest)
        bs.run_batch_command([
            "rsync", "-rlptD",
            self._pm.project_source_dir() + "/build_" + self._o.arch +
            "/modules", dest
        ])
        bs.Export().export()


bs.build(
    DeqpBuilder(extra_definitions=[
        "-DDEQP_TARGET=x11_egl", "-DDEQP_GLES1_LIBRARIES=/tmp/build_root/" +
        bs.Options().arch + "/lib/libGL.so"
    ]))
Example #24
0
 def __init__(self):
     self.opts = bs.Options()
Example #25
0
def test_project_invoke():
    #pytest.set_trace()
    args = ["ignore_arg0", "--action=build,test", "--config=debug"]
    pi = bs.ProjectInvoke(bs.Options(args), project="mesa")
    pis = str(pi)
    assert (pis == str(bs.ProjectInvoke(from_string=pis)))
Example #26
0
if os.path.exists(bisect_dir):
    print "Removing existing retest."
    mvdir = os.path.normpath(bisect_dir + "/../" +
                             datetime.datetime.now().isoformat())
    os.rename(bisect_dir, mvdir)

cmd = ["rsync", "-rlptD", "/".join(dirnames[:-1]) + "/", bisect_dir]
bs.run_batch_command(cmd)
bs.rmtree(bisect_dir + "/test")
bs.rmtree(bisect_dir + "/piglit-test")
bs.rmtree(bisect_dir + "/deqp-test")
bs.rmtree(bisect_dir + "/cts-test")
bs.rmtree(bisect_dir + "/crucible-test")

j = bs.Jenkins(_revspec, bisect_dir)
o = bs.Options(["bisect_all.py"])
o.result_path = bisect_dir
o.retest_path = args.result_path
depGraph = bs.DependencyGraph(["piglit-gpu-all"], o)

print "Retesting mesa to: " + bisect_dir
try:
    j.build_all(depGraph, print_summary=False)
except bs.BuildFailure:
    print "ERROR: some builds failed"

# make sure there is enough time for the test files to sync to nfs
time.sleep(20)
reproduced_failures = bs.TestLister(bisect_dir + "/test/")

print "Found failures:"
Example #27
0
 def __init__(self):
     self.hardware = bs.Options().hardware
Example #28
0
    def test(self):
        pm = bs.ProjectMap()
        build_root = pm.build_root()
        global_opts = bs.Options()
        if global_opts.arch == "m64":
            icd_name = "intel_icd.x86_64.json"
        elif global_opts.arch == "m32":
            icd_name = "intel_icd.i686.json"
        env = {
            "LD_LIBRARY_PATH": build_root + "/lib",
            "VK_ICD_FILENAMES": build_root + "/share/vulkan/icd.d/" + icd_name,
            "ANV_ABORT_ON_DEVICE_LOSS": "true"
        }
        o = bs.Options()
        o.update_env(env)
        br = bs.ProjectMap().build_root()
        out_dir = br + "/../test"
        if not path.exists(out_dir):
            os.makedirs(out_dir)
        out_xml = out_dir + "/piglit-crucible_" + o.hardware + "_" + o.arch + ".xml"
        include_tests = []
        if o.retest_path:
            include_tests = bs.TestLister(
                o.retest_path + "/test/").RetestIncludes("crucible-test")

        # flaky
        excludes = ["!func.query.timestamp", "!func.ssbo.interleve"]
        parallelism = []

        if "hsw" in o.hardware:
            # issue 4
            excludes += [
                "!func.copy.copy-buffer.large",
                "!func.interleaved-cmd-buffers.end1*",
                "!func.miptree.d32-sfloat.aspect-depth.view*",
                "!func.miptree.r8g8b8a8-unorm.aspect-color.view*",
                "!func.miptree.s8-uint.aspect-stencil*",
                "!func.renderpass.clear.color08", "!func.ssbo.interleve"
            ]
        if "ivb" in o.hardware:
            # issue 5
            excludes += [
                "!func.depthstencil*",
                "!func.miptree.r8g8b8a8-unorm.aspect-color.view*",
                "!func.miptree.s8-uint.aspect-stencil*",
                "!func.miptree.d32-sfloat.aspect-depth.view*",
                "!stress.lots-of-surface-state.fs.static"
            ]
            parallelism = ['-j', '1']

        if "byt" in o.hardware:
            # issue 6
            excludes += [
                "!func.miptree.d32-sfloat.aspect-depth.view-3d.levels0*",
                "!func.depthstencil*", "!func.miptree.s8-uint.aspect-stencil*",
                "!stress.lots-of-surface-state.fs.static"
            ]
            parallelism = ['-j', '1']

        if "bsw" in o.hardware:
            excludes += ["!func.event.cmd_buffer"]  # intermittent fail/crash

        if "bxt" in o.hardware:
            excludes += [
                "!func.miptree.s8-uint.aspect-stencil*",
                "!stress.lots-of-surface-state.fs.static"
            ]

        bs.run_batch_command([
            br + "/bin/crucible", "run", "--fork", "--log-pids",
            "--junit-xml=" + out_xml
        ] + parallelism + include_tests + excludes,
                             env=env,
                             expected_return_code=None)
        post_process_results(out_xml)
        bs.run_batch_command(["cp", "-a", "-n", out_dir, pm.source_root()])

        bs.check_gpu_hang()
        bs.Export().export_tests()
Example #29
0
 def __init__(self):
     self._pm = bs.ProjectMap()
     self._options = bs.Options()
     self._src_dir = self._pm.project_source_dir()
     self._build_dir = self._src_dir + "/build_" + self._options.arch
     self._build_root = self._pm.build_root()
Example #30
0
def main():

    # reuse the options from the gasket
    o = bs.Options([sys.argv[0]])
    description = "builds a component on jenkins"
    parser = argparse.ArgumentParser(description=description,
                                     parents=[o._parser],
                                     conflict_handler="resolve")

    parser.add_argument('--branch', type=str, default="mesa_master",
                        help="Branch specification to build.  "\
                        "See build_specification.xml/branches")

    parser.add_argument('--revision',
                        type=str,
                        default="",
                        help="specific set of revisions to build.")

    parser.add_argument('--test', type=str, default=None,
                        help="Name of test to execute.  Arch/hardware suffix "\
                        "will override those options")

    args = parser.parse_args()
    branch = args.branch
    revision = args.revision
    test = args.test

    # some build_local params are not handled by the Options, which is
    # used by other modules.  This code strips out incompatible args
    o = bs.Options(["bogus"])
    vdict = vars(args)
    del vdict["branch"]
    del vdict["revision"]
    del vdict["test"]

    # override hardware/arch with suffix if available
    if not test:
        print "ERROR: --test argument required"
        sys.exit(-1)

    test_suffix = test.split(".")[-1]
    if test_suffix[-3:] in ["m32", "m64"]:
        vdict["arch"] = test_suffix[-3:]
        vdict["hardware"] = test_suffix[:-3]
    else:
        if vdict["hardware"] == "builder":
            # can't run tests on a builder
            vdict["hardware"] = "bdwgt2"
        # set the suffix in the way that piglit-test expects, eg "ilkm32"
        test = test + "." + vdict["hardware"] + vdict["arch"]

    o.__dict__.update(vdict)
    sys.argv = ["bogus"] + o.to_list()

    # check out the branch, refined by any manually-specfied revisions
    bspec = bs.BuildSpecification()
    bspec.checkout(branch)
    if (revision):
        revspec = bs.RevisionSpecification.from_cmd_line_param(
            revision.split())
        revspec.checkout()

    revspec = bs.RevisionSpecification()
    print "Building revision: " + revspec.to_cmd_line_param()

    # create a result_path that is unique for this set of builds
    spec_xml = bs.ProjectMap().build_spec()
    results_dir = spec_xml.find("build_master").attrib["results_dir"]
    result_path = "/".join([
        results_dir, branch,
        revspec.to_cmd_line_param().replace(" ", "_"), "single_test"
    ])
    o.result_path = result_path

    # allow re-execution of tests (if different test was specified)
    bs.rmtree(result_path + "/test")

    depGraph = bs.DependencyGraph("piglit-test", o)
    bi = bs.ProjectInvoke(project="piglit-test", options=o)

    # remove the test build, because we want to build it directly
    depGraph.build_complete(bi)
    bi.set_info("status", "single-test-rebuild")

    jen = bs.Jenkins(result_path=result_path, revspec=revspec)
    jen.build_all(depGraph)
    jen.build(bi, extra_arg="--piglit_test=" + test)
    jen.wait_for_build()
    time.sleep(10)

    pm = bs.ProjectMap()
    out_test_dir = pm.output_dir()
    if os.path.exists(out_test_dir):
        bs.rmtree(out_test_dir)
    os.makedirs(out_test_dir)
    collate_tests(result_path, out_test_dir)