summaryrefslogtreecommitdiffstats
path: root/src/VBox/ValidationKit/docs/AutomaticTestingRevamp.html
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/VBox/ValidationKit/docs/AutomaticTestingRevamp.html1354
1 files changed, 1354 insertions, 0 deletions
diff --git a/src/VBox/ValidationKit/docs/AutomaticTestingRevamp.html b/src/VBox/ValidationKit/docs/AutomaticTestingRevamp.html
new file mode 100644
index 00000000..f5501717
--- /dev/null
+++ b/src/VBox/ValidationKit/docs/AutomaticTestingRevamp.html
@@ -0,0 +1,1354 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
+<title>AutomaticTestingRevamp.txt</title>
+<style type="text/css">
+
+/*
+:Author: David Goodger (goodger@python.org)
+:Id: $Id: AutomaticTestingRevamp.html $
+:Copyright: This stylesheet has been placed in the public domain.
+
+Default cascading style sheet for the HTML output of Docutils.
+
+See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
+customize this style sheet.
+*/
+
+/* used to remove borders from tables and images */
+.borderless, table.borderless td, table.borderless th {
+ border: 0 }
+
+table.borderless td, table.borderless th {
+ /* Override padding for "table.docutils td" with "! important".
+ The right padding separates the table cells. */
+ padding: 0 0.5em 0 0 ! important }
+
+.first {
+ /* Override more specific margin styles with "! important". */
+ margin-top: 0 ! important }
+
+.last, .with-subtitle {
+ margin-bottom: 0 ! important }
+
+.hidden {
+ display: none }
+
+.subscript {
+ vertical-align: sub;
+ font-size: smaller }
+
+.superscript {
+ vertical-align: super;
+ font-size: smaller }
+
+a.toc-backref {
+ text-decoration: none ;
+ color: black }
+
+blockquote.epigraph {
+ margin: 2em 5em ; }
+
+dl.docutils dd {
+ margin-bottom: 0.5em }
+
+object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
+ overflow: hidden;
+}
+
+/* Uncomment (and remove this text!) to get bold-faced definition list terms
+dl.docutils dt {
+ font-weight: bold }
+*/
+
+div.abstract {
+ margin: 2em 5em }
+
+div.abstract p.topic-title {
+ font-weight: bold ;
+ text-align: center }
+
+div.admonition, div.attention, div.caution, div.danger, div.error,
+div.hint, div.important, div.note, div.tip, div.warning {
+ margin: 2em ;
+ border: medium outset ;
+ padding: 1em }
+
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title {
+ font-weight: bold ;
+ font-family: sans-serif }
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title, .code .error {
+ color: red ;
+ font-weight: bold ;
+ font-family: sans-serif }
+
+/* Uncomment (and remove this text!) to get reduced vertical space in
+ compound paragraphs.
+div.compound .compound-first, div.compound .compound-middle {
+ margin-bottom: 0.5em }
+
+div.compound .compound-last, div.compound .compound-middle {
+ margin-top: 0.5em }
+*/
+
+div.dedication {
+ margin: 2em 5em ;
+ text-align: center ;
+ font-style: italic }
+
+div.dedication p.topic-title {
+ font-weight: bold ;
+ font-style: normal }
+
+div.figure {
+ margin-left: 2em ;
+ margin-right: 2em }
+
+div.footer, div.header {
+ clear: both;
+ font-size: smaller }
+
+div.line-block {
+ display: block ;
+ margin-top: 1em ;
+ margin-bottom: 1em }
+
+div.line-block div.line-block {
+ margin-top: 0 ;
+ margin-bottom: 0 ;
+ margin-left: 1.5em }
+
+div.sidebar {
+ margin: 0 0 0.5em 1em ;
+ border: medium outset ;
+ padding: 1em ;
+ background-color: #ffffee ;
+ width: 40% ;
+ float: right ;
+ clear: right }
+
+div.sidebar p.rubric {
+ font-family: sans-serif ;
+ font-size: medium }
+
+div.system-messages {
+ margin: 5em }
+
+div.system-messages h1 {
+ color: red }
+
+div.system-message {
+ border: medium outset ;
+ padding: 1em }
+
+div.system-message p.system-message-title {
+ color: red ;
+ font-weight: bold }
+
+div.topic {
+ margin: 2em }
+
+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
+ margin-top: 0.4em }
+
+h1.title {
+ text-align: center }
+
+h2.subtitle {
+ text-align: center }
+
+hr.docutils {
+ width: 75% }
+
+img.align-left, .figure.align-left, object.align-left, table.align-left {
+ clear: left ;
+ float: left ;
+ margin-right: 1em }
+
+img.align-right, .figure.align-right, object.align-right, table.align-right {
+ clear: right ;
+ float: right ;
+ margin-left: 1em }
+
+img.align-center, .figure.align-center, object.align-center {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table.align-center {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.align-left {
+ text-align: left }
+
+.align-center {
+ clear: both ;
+ text-align: center }
+
+.align-right {
+ text-align: right }
+
+/* reset inner alignment in figures */
+div.align-right {
+ text-align: inherit }
+
+/* div.align-center * { */
+/* text-align: left } */
+
+.align-top {
+ vertical-align: top }
+
+.align-middle {
+ vertical-align: middle }
+
+.align-bottom {
+ vertical-align: bottom }
+
+ol.simple, ul.simple {
+ margin-bottom: 1em }
+
+ol.arabic {
+ list-style: decimal }
+
+ol.loweralpha {
+ list-style: lower-alpha }
+
+ol.upperalpha {
+ list-style: upper-alpha }
+
+ol.lowerroman {
+ list-style: lower-roman }
+
+ol.upperroman {
+ list-style: upper-roman }
+
+p.attribution {
+ text-align: right ;
+ margin-left: 50% }
+
+p.caption {
+ font-style: italic }
+
+p.credits {
+ font-style: italic ;
+ font-size: smaller }
+
+p.label {
+ white-space: nowrap }
+
+p.rubric {
+ font-weight: bold ;
+ font-size: larger ;
+ color: maroon ;
+ text-align: center }
+
+p.sidebar-title {
+ font-family: sans-serif ;
+ font-weight: bold ;
+ font-size: larger }
+
+p.sidebar-subtitle {
+ font-family: sans-serif ;
+ font-weight: bold }
+
+p.topic-title {
+ font-weight: bold }
+
+pre.address {
+ margin-bottom: 0 ;
+ margin-top: 0 ;
+ font: inherit }
+
+pre.literal-block, pre.doctest-block, pre.math, pre.code {
+ margin-left: 2em ;
+ margin-right: 2em }
+
+pre.code .ln { color: grey; } /* line numbers */
+pre.code, code { background-color: #eeeeee }
+pre.code .comment, code .comment { color: #5C6576 }
+pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
+pre.code .literal.string, code .literal.string { color: #0C5404 }
+pre.code .name.builtin, code .name.builtin { color: #352B84 }
+pre.code .deleted, code .deleted { background-color: #DEB0A1}
+pre.code .inserted, code .inserted { background-color: #A3D289}
+
+span.classifier {
+ font-family: sans-serif ;
+ font-style: oblique }
+
+span.classifier-delimiter {
+ font-family: sans-serif ;
+ font-weight: bold }
+
+span.interpreted {
+ font-family: sans-serif }
+
+span.option {
+ white-space: nowrap }
+
+span.pre {
+ white-space: pre }
+
+span.problematic {
+ color: red }
+
+span.section-subtitle {
+ /* font-size relative to parent (h1..h6 element) */
+ font-size: 80% }
+
+table.citation {
+ border-left: solid 1px gray;
+ margin-left: 1px }
+
+table.docinfo {
+ margin: 2em 4em }
+
+table.docutils {
+ margin-top: 0.5em ;
+ margin-bottom: 0.5em }
+
+table.footnote {
+ border-left: solid 1px black;
+ margin-left: 1px }
+
+table.docutils td, table.docutils th,
+table.docinfo td, table.docinfo th {
+ padding-left: 0.5em ;
+ padding-right: 0.5em ;
+ vertical-align: top }
+
+table.docutils th.field-name, table.docinfo th.docinfo-name {
+ font-weight: bold ;
+ text-align: left ;
+ white-space: nowrap ;
+ padding-left: 0 }
+
+/* "booktabs" style (no vertical lines) */
+table.docutils.booktabs {
+ border: 0px;
+ border-top: 2px solid;
+ border-bottom: 2px solid;
+ border-collapse: collapse;
+}
+table.docutils.booktabs * {
+ border: 0px;
+}
+table.docutils.booktabs th {
+ border-bottom: thin solid;
+ text-align: left;
+}
+
+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
+ font-size: 100% }
+
+ul.auto-toc {
+ list-style-type: none }
+
+</style>
+</head>
+<body>
+<div class="document">
+
+
+<div class="section" id="revamp-of-automatic-virtualbox-testing">
+<h1>Revamp of Automatic VirtualBox Testing</h1>
+<div class="section" id="introduction">
+<h2>Introduction</h2>
+<p>This is the design document for a revamped automatic testing framework.
+The revamp aims at replacing the current tinderbox based testing by a new
+system that is written from scratch.</p>
+<p>The old system is not easy to work with and was never meant to be used for
+managing tests, after all it just a simple a build manager tailored for
+contiguous building. Modifying the existing tinderbox system to do what
+we want would require fundamental changes that would render it useless as
+a build manager, it would therefore end up as a fork. The amount of work
+required would probably be about the same as writing a new system from
+scratch. Other considerations, such as the license of the tinderbox
+system (MPL) and language it is realized in (Perl), are also in favor of
+doing it from scratch.</p>
+<p>The language envisioned for the new automatic testing framework is Python. This
+is for several reasons:</p>
+<blockquote>
+<ul class="simple">
+<li>The VirtualBox API has Python bindings.</li>
+<li>Python is used quite a bit inside Sun (dunno about Oracle).</li>
+<li>Works relatively well with Apache for the server side bits.</li>
+<li>It is more difficult to produce write-only code in Python (alias the
+we-don't-like-perl argument).</li>
+<li>You don't need to compile stuff.</li>
+</ul>
+</blockquote>
+<p>Note that the author of this document has no special training as a test
+engineer and may therefore be using the wrong terms here and there. The
+primary focus is to express what we need to do in order to improve
+testing.</p>
+<p>This document is written in reStructuredText (rst) which just happens to
+be used by Python, the primary language for this revamp. For more
+information on reStructuredText: <a class="reference external" href="http://docutils.sourceforge.net/rst.html">http://docutils.sourceforge.net/rst.html</a></p>
+</div>
+</div>
+<div class="section" id="definitions-glossary">
+<h1>Definitions / Glossary</h1>
+<dl class="docutils">
+<dt>sub-test driver</dt>
+<dd>A set of test cases that can be used by more than one test driver. Could
+also be called a test unit, in the pascal sense of unit, if it wasn't so
+easily confused with 'unit test'.</dd>
+<dt>test</dt>
+<dd>This is somewhat ambiguous and this document try avoid using it where
+possible. When used it normally refers to doing testing by executing one or
+more testcases.</dd>
+<dt>test case</dt>
+<dd>A set of inputs, test programs and expected results. It validates system
+requirements and generates a pass or failed status. A basic unit of testing.
+Note that we use the term in a rather broad sense.</dd>
+<dt>test driver</dt>
+<dd>A program/script used to execute a test. Also known as a test harness.
+Generally abbreviated 'td'. It can have sub-test drivers.</dd>
+<dt>test manager</dt>
+<dd>Software managing the automatic testing. This is a web application that runs
+on a dedicated server (tindertux).</dd>
+<dt>test set</dt>
+<dd>The output of testing activity. Logs, results, ++. Our usage of this should
+probably be renamed to 'test run'.</dd>
+<dt>test group</dt>
+<dd>A collection of related test cases.</dd>
+<dt>testbox</dt>
+<dd>A computer that does testing.</dd>
+<dt>testbox script</dt>
+<dd>Script executing orders from the test manager on a testbox. Started
+automatically upon bootup.</dd>
+<dt>testing</dt>
+<dd>todo</dd>
+<dt>TODO: Check that we've got all this right and make them more exact</dt>
+<dd>where possible.</dd>
+</dl>
+<p>See also <a class="reference external" href="http://encyclopedia2.thefreedictionary.com/testing%20types">http://encyclopedia2.thefreedictionary.com/testing%20types</a>
+and <a class="reference external" href="http://www.aptest.com/glossary.html">http://www.aptest.com/glossary.html</a> .</p>
+</div>
+<div class="section" id="objectives">
+<h1>Objectives</h1>
+<blockquote>
+<ul class="simple">
+<li>A scalable test manager (&gt;200 testboxes).</li>
+<li>Optimize the web user interface (WUI) for typical workflows and analysis.</li>
+<li>Efficient and flexibile test configuration.</li>
+<li>Import test result from other test systems (logo testing, VDI, ++).</li>
+<li>Easy to add lots of new testscripts.</li>
+<li>Run tests locally without a manager.</li>
+<li>Revamp a bit at the time.</li>
+</ul>
+</blockquote>
+</div>
+<div class="section" id="the-testbox-side">
+<h1>The Testbox Side</h1>
+<p>Each testbox has a unique name corresponding to its DNS zone entry. When booted
+a testbox script is started automatically. This script will query the test
+manager for orders and execute them. The core order downloads and executes a
+test driver with parameters (configuration) from the server. The test driver
+does all the necessary work for executing the test. In a typical VirtualBox
+test this means picking a build, installing it, configuring VMs, running the
+test VMs, collecting the results, submitting them to the server, and finally
+cleaning up afterwards.</p>
+<p>The testbox environment which the test drivers are executed in will have a
+number of environment variables for determining location of the source images
+and other test data, scratch space, test set id, server URL, and so on and so
+forth.</p>
+<p>On startup, the testbox script will look for crash dumps and similar on
+systems where this is possible. If any sign of a crash is found, it will
+put any dumps and reports in the upload directory and inform the test
+manager before reporting for duty. In order to generate the proper file
+names and report the crash in the right test set as well as prevent
+reporting crashes unrelated to automatic testing, the testbox script will
+keep information (test set id, ++) in a separate scratch directory
+(${TESTBOX_PATH_SCRATCH}/../testbox) and make sure it is synced to the
+disk (both files and directories).</p>
+<p>After checking for crashes, the testbox script will clean up any previous test
+which might be around. This involves first invoking the test script in cleanup
+mode and the wiping the scratch space.</p>
+<p>When reporting for duty the script will submit information about the host: OS
+name, OS version, OS bitness, CPU vendor, total number of cores, VT-x support,
+AMD-V support, amount of memory, amount of scratch space, and anything else that
+can be found useful for scheduling tests or filtering test configurations.</p>
+<div class="section" id="testbox-script-orders">
+<h2>Testbox Script Orders</h2>
+<p>The orders are kept in a queue on the server and the testbox script will fetch
+them one by one. Orders that cannot be executed at the moment will be masked in
+the query from the testbox.</p>
+<dl class="docutils">
+<dt>Execute Test Driver</dt>
+<dd>Downloads and executes the a specified test driver with the given
+configuration (arguments). Only one test driver can be executed at a time.
+The server can specify more than one ZIP file to be downloaded and unpacked
+before executing the test driver. The testbox script may cache these zip
+files using http time stamping.</dd>
+<dt>Abort Test Driver</dt>
+<dd>Aborts the current test driver. This will drop a hint to the driver and give
+it 60 seconds to shut down the normal way. If that fails, the testbox script
+will kill the driver processes (SIGKILL or equivalent), invoke the
+testdriver in cleanup mode, and finally wipe the scratch area. Should either
+of the last two steps fail in some way, the testbox will be rebooted.</dd>
+<dt>Idle</dt>
+<dd>Ask again in X seconds, where X is specified by the server.</dd>
+<dt>Reboot</dt>
+<dd>Reboot the testbox. If a test driver is current running, an attempt at
+aborting it (Abort Test Driver) will be made first.</dd>
+<dt>Update</dt>
+<dd>Updates the testbox script. The order includes a server relative path to the
+new testbox script. This can only be executed when no test driver is
+currently being executed.</dd>
+</dl>
+</div>
+<div class="section" id="testbox-environment-variables">
+<h2>Testbox Environment: Variables</h2>
+<dl class="docutils">
+<dt>COMSPEC</dt>
+<dd>This will be set to C:WindowsSystem32cmd.exe on Windows.</dd>
+<dt>PATH</dt>
+<dd>This will contain the kBuild binary directory for the host platform.</dd>
+<dt>SHELL</dt>
+<dd>This will be set to point to kmk_ash(.exe) on all platforms.</dd>
+<dt>TESTBOX_NAME</dt>
+<dd>The testbox name.
+This is not required by the local reporter.</dd>
+<dt>TESTBOX_PATH_BUILDS</dt>
+<dd>The absolute path to where the build repository can be found. This should be
+a read only mount when possible.</dd>
+<dt>TESTBOX_PATH_RESOURCES</dt>
+<dd>The absolute path to where static test resources like ISOs and VDIs can be
+found. The test drivers knows the layout of this. This should be a read only
+mount when possible.</dd>
+<dt>TESTBOX_PATH_SCRATCH</dt>
+<dd>The absolute path to the scratch space. This is the current directory when
+starting the test driver. It will be wiped automatically after executing the
+test.
+(Envisioned as ${TESTBOX_PATH_SCRIPTS}/../scratch and that
+${TESTBOX_PATH_SCRATCH}/ will be automatically wiped by the testbox script.)</dd>
+<dt>TESTBOX_PATH_SCRIPTS</dt>
+<dd>The absolute path to the test driver and the other files that was unzipped
+together with it. This is also where the test-driver-abort file will be put.
+(Envisioned as ${TESTBOX_PATH_SCRATCH}/../driver, see above.)</dd>
+<dt>TESTBOX_PATH_UPLOAD</dt>
+<dd>The absolute path to the upload directory for the testbox. This is for
+putting VOBs, PNGs, core dumps, crash dumps, and such on. The files should be
+bzipped or zipped if they aren't compress already. The names should contain
+the testbox and test set ID.</dd>
+<dt>TESTBOX_REPORTER</dt>
+<dd>The name of the test reporter back end. If not present, it will default to
+the local reporter.</dd>
+<dt>TESTBOX_TEST_SET_ID</dt>
+<dd>The test set ID if we're running.
+This is not required by the local reporter.</dd>
+<dt>TESTBOX_MANAGER_URL</dt>
+<dd>The URL to the test manager.
+This is not required by the local reporter.</dd>
+<dt>TESTBOX_XYZ</dt>
+<dd>There will probably be some more of these.</dd>
+</dl>
+</div>
+<div class="section" id="testbox-environment-core-utilities">
+<h2>Testbox Environment: Core Utilities</h2>
+<p>The testbox will not provide the typical unix /bin and /usr/bin utilities. In
+other words, cygwin will not be used on Windows!</p>
+<p>The testbox will provide the unixy utilities that ships with kBuild and possibly
+some additional ones from tools/<em>.</em>/bin in the VirtualBox tree (wget, unzip,
+zip, and so on). The test drivers will avoid invoking any of these utilities
+directly and instead rely on generic utility methods in the test driver
+framework. That way we can more easily reimplement the functionality of the
+core utilities and drop the dependency on them. It also allows us to quickly
+work around platform specific oddities and bugs.</p>
+</div>
+<div class="section" id="test-drivers">
+<h2>Test Drivers</h2>
+<p>The test drivers are programs that will do the actual testing. In addition to
+run under the testbox script, they can be executed in the VirtualBox development
+environment. This is important for bug analysis and for simplifying local
+testing by the developers before committing changes. It also means the test
+drivers can be developed locally in the VirtualBox development environment.</p>
+<p>The main difference between executing a driver under the testbox script and
+running it manually is that there is no test manager in the latter case. The
+test result reporter will not talk to the server, but report things to a local
+log file and/or standard out/err. When invoked manually, all the necessary
+arguments will need to be specified by hand of course - it should be possible
+to extract them from a test set as well.</p>
+<p>For the early implementation stages, an implementation of the reporter interface
+that talks to the tinderbox base test manager will be needed. This will be
+dropped later on when a new test manager is ready.</p>
+<p>As hinted at in other sections, there will be a common framework
+(libraries/packages/classes) for taking care of the tedious bits that every
+test driver needs to do. Sharing code is essential to easing test driver
+development as well as reducing their complexity. The framework will contain:</p>
+<blockquote>
+<ul class="simple">
+<li>A generic way of submitting output. This will be a generic interface with
+multiple implementation, the TESTBOX_REPORTER environment variable
+will decide which of them to use. The interface will have very specific
+methods to allow the reporter to do a best possible job in reporting the
+results to the test manager.</li>
+<li><dl class="first docutils">
+<dt>Helpers for typical tasks, like:</dt>
+<dd><ul class="first last">
+<li>Copying files.</li>
+<li>Deleting files, directory trees and scratch space.</li>
+<li>Unzipping files.</li>
+<li>Creating ISOs</li>
+<li>And such things.</li>
+</ul>
+</dd>
+</dl>
+</li>
+<li>Helpers for installing and uninstalling VirtualBox.</li>
+<li>Helpers for defining VMs. (The VBox API where available.)</li>
+<li>Helpers for controlling VMs. (The VBox API where available.)</li>
+</ul>
+</blockquote>
+<p>The VirtualBox bits will be separate from the more generic ones, simply because
+this is cleaner it will allow us to reuse the system for testing other products.</p>
+<p>The framework will be packaged in a zip file other than the test driver so we
+don't waste time and space downloading the same common code.</p>
+<p>The test driver will poll for the file
+${TESTBOX_PATH_SCRIPTS}/test-driver-abort and abort all testing when it sees it.</p>
+<p>The test driver can be invoked in three modes: execute, help and cleanup. The
+default is execute mode, the help shows an configuration summary and the cleanup
+is for cleaning up after a reboot or aborted run. The latter is done by the
+testbox script on startup and after abort - the driver is expected to clean up
+by itself after a normal run.</p>
+</div>
+</div>
+<div class="section" id="the-server-side">
+<h1>The Server Side</h1>
+<p>The server side will be implemented using a webserver (apache), a database
+(postgres) and cgi scripts (Python). In addition a cron job (Python) running
+once a minute will generate static html for frequently used pages and maybe
+execute some other tasks for driving the testing forwards. The order queries
+from the testbox script is the primary driving force in the system. The total
+makes up the test manager.</p>
+<p>The test manager can be split up into three rough parts:</p>
+<blockquote>
+<ul class="simple">
+<li>Configuration (of tests, testgroups and testboxes).</li>
+<li>Execution (of tests, collecting and organizing the output).</li>
+<li>Analysis (of test output, mostly about presentation).</li>
+</ul>
+</blockquote>
+</div>
+<div class="section" id="test-manager-requirements">
+<h1>Test Manager: Requirements</h1>
+<p>List of requirements:</p>
+<blockquote>
+<ul class="simple">
+<li>Two level testing - L1 quick smoke tests and L2 longer tests performed on
+builds passing L1. (Klaus (IIRC) meant this could be realized using
+test dependency.)</li>
+<li>Black listing builds (by revision or similar) known to be bad.</li>
+<li>Distinguish between build types so we can do a portion of the testing with
+strict builds.</li>
+<li>Easy to re-configure build source for testing different branch or for
+testing a release candidate. (Directory based is fine.)</li>
+<li>Useful to be able to partition testboxes (run specific builds on some
+boxes, let an engineer have a few boxes for a while).</li>
+<li>Interaction with ILOM/...: reset systems.</li>
+<li>Be able to suspend testing on selected testboxes when doing maintenance
+(where automatically resuming testing on reboot is undesired) or similar
+activity.</li>
+<li>Abort testing on selected testboxes.</li>
+<li>Scheduling of tests requiring more than one testbox.</li>
+<li>Scheduling of tests that cannot be executing concurrently on several
+machines because of some global resource like an iSCSI target.</li>
+<li>Jump the scheduling queue. Scheduling of specified test the next time a
+testbox is available (optionally specifying which testbox to schedule it
+on).</li>
+<li><dl class="first docutils">
+<dt>Configure tests with variable configuration to get better coverage. Two modes:</dt>
+<dd><ul class="first last">
+<li>TM generates the permutations based on one or more sets of test script arguments.</li>
+<li>Each configuration permutation is specified manually.</li>
+</ul>
+</dd>
+</dl>
+</li>
+<li>Test specification needs to be flexible (select tests, disable test, test
+scheduling (run certain tests nightly), ... ).</li>
+<li>Test scheduling by hour+weekday and by priority.</li>
+<li>Test dependencies (test A depends on test B being successful).</li>
+<li>Historize all configuration data, in particular test configs (permutations
+included) and testboxes.</li>
+<li>Test sets has at a minimum a build reference, a testbox reference and a
+primary log associated with it.</li>
+<li><dl class="first docutils">
+<dt>Test sets stores further result as a recursive collection of:</dt>
+<dd><ul class="first last">
+<li>hierarchical subtest name (slash sep)</li>
+<li>test parameters / config</li>
+<li>bool fail/succ</li>
+<li>attributes (typed?)</li>
+<li>test time</li>
+<li>e.g. throughput</li>
+<li>subresults</li>
+<li>log</li>
+<li>screenshots, video,...</li>
+</ul>
+</dd>
+</dl>
+</li>
+<li>The test sets database structure needs to designed such that data mining
+can be done in an efficient manner.</li>
+<li>Presentation/analysis: graphs!, categorize bugs, columns reorganizing
+grouped by test (hierarchical), overviews, result for last day.</li>
+</ul>
+</blockquote>
+</div>
+<div class="section" id="test-manager-configuration">
+<h1>Test Manager: Configuration</h1>
+<div class="section" id="testboxes">
+<h2>Testboxes</h2>
+<p>Configuration of testboxes doesn't involve much work normally. A testbox
+is added manually to the test manager by entering the DNS entry and/or IP
+address (the test manager resolves the missing one when necessary) as well as
+the system UUID (when obtainable - should be displayed by the testbox script
+installer). Queries from unregistered testboxes will be declined as a kind of
+security measure, the incident should be logged in the webserver log if
+possible. In later dealings with the client the System UUID will be the key
+identifier. It's permittable for the IP address to change when the testbox
+isn't online, but not while testing (just imagine live migration tests and
+network tests). Ideally, the testboxes should not change IP address.</p>
+<p>The testbox edit function must allow changing the name and system UUID.</p>
+<p>One further idea for the testbox configuration is indicating what they are
+capable of to filter out tests and test configurations that won't work on that
+testbox. To examplify this take the ACP2 installation test. If the test
+manager does not make sure the testbox have VT-x or AMD-v capabilities, the test
+is surely going to fail. Other testbox capabilities would be total number of
+CPU cores, memory size, scratch space. These testbox capabilities should be
+collected automatically on bootup by the testbox script together with OS name,
+OS version and OS bitness.</p>
+<p>A final thought, instead of outright declining all requests from new testboxes,
+we could record the unregistered testboxes with ip, UUID, name, os info and
+capabilities but mark them as inactive. The test operator can then activate
+them on an activation page or edit the testbox or something.</p>
+</div>
+<div class="section" id="testcases">
+<h2>Testcases</h2>
+<p>We use the term testcase for a test.</p>
+</div>
+<div class="section" id="testgroups">
+<h2>Testgroups</h2>
+<p>Testcases are organized into groups. A testcase can be member of more than one
+group. The testcase gets a priority assigned to it in connection with the
+group membership.</p>
+<p>Testgroups are picked up by a testbox partition (aka scheduling group) and a
+prioirty, scheduling time restriction and dependencies on other test groups are
+associated with the assignment. A testgroup can be used by several testbox
+partitions.</p>
+<p>(This used to be called 'testsuites' but was renamed to avoid confusion with
+the VBox Test Suite.)</p>
+</div>
+<div class="section" id="scheduling">
+<h2>Scheduling</h2>
+<p>The initial scheduler will be modelled after what we're doing already on in the
+tinderbox driven testing. It's best described as a best effort continuous
+integration scheduler. Meaning, it will always use the latest build suitable
+for a testcase. It will schedule on a testcase level, using the combined
+priority of the testcase in the test group and the test group with the testbox
+partition, trying to spread the test case argument variation out accordingly
+over the whole scheduilng queue. Which argument variation to start with, is
+not undefined (random would be best).</p>
+<p>Later, we may add other schedulers as needed.</p>
+</div>
+</div>
+<div class="section" id="the-test-manager-database">
+<h1>The Test Manager Database</h1>
+<p>First a general warning:</p>
+<blockquote>
+The guys working on this design are not database experts, web
+programming experts or similar, rather we are low level guys
+who's main job is x86 &amp; AMD64 virtualization. So, please don't
+be too hard on us. :-)</blockquote>
+<p>A logical table layout can be found in TestManagerDatabaseMap.png (created by
+Oracle SQL Data Modeler, stored in TestManagerDatabase.dmd). The physical
+database layout can be found in TestManagerDatabaseInit.pgsql postgreSQL
+script. The script is commented.</p>
+<div class="section" id="data-history">
+<h2>Data History</h2>
+<p>We need to somehow track configuration changes over time. We also need to
+be able to query the exact configuration a test set was run with so we can
+understand and make better use of the results.</p>
+<p>There are different techniques for archiving this, one is tuple-versioning
+( <a class="reference external" href="http://en.wikipedia.org/wiki/Tuple-versioning">http://en.wikipedia.org/wiki/Tuple-versioning</a> ), another is log trigger
+( <a class="reference external" href="http://en.wikipedia.org/wiki/Log_trigger">http://en.wikipedia.org/wiki/Log_trigger</a> ). We use tuple-versioning in
+this database, with 'effective' as start date field name and 'expire' as
+the end (exclusive).</p>
+<p>Tuple-versioning has a shortcoming wrt to keys, both primary and foreign.
+The primary key of a table employing tuple-versioning is really
+'id' + 'valid_period', where the latter is expressed using two fields
+([effective...expire-1]). Only, how do you tell the database engine that
+it should not allow overlapping valid_periods? Useful suggestions are
+welcomed. :-)</p>
+<p>Foreign key references to a table using tuple-versioning is running into
+trouble because of the time axis and that to our knowledge foreign keys
+must reference exactly one row in the other table. When time is involved
+what we wish to tell the database is that at any given time, there actually
+is exactly one row we want to match in the other table, only we've no idea
+how to express this. So, many foreign keys are not expressed in SQL of this
+database.</p>
+<p>In some cases, we extend the tuple-versioning with a generation ID so that
+normal foreign key referencing can be used. We only use this for recording
+(references in testset) and scheduling (schedqueue), as using it more widely
+would force updates (gen_id changes) to propagate into all related tables.</p>
+<dl class="docutils">
+<dt>See also:</dt>
+<dd><ul class="first last simple">
+<li><a class="reference external" href="http://en.wikipedia.org/wiki/Slowly_changing_dimension">http://en.wikipedia.org/wiki/Slowly_changing_dimension</a></li>
+<li><a class="reference external" href="http://en.wikipedia.org/wiki/Change_data_capture">http://en.wikipedia.org/wiki/Change_data_capture</a></li>
+<li><a class="reference external" href="http://en.wikipedia.org/wiki/Temporal_database">http://en.wikipedia.org/wiki/Temporal_database</a></li>
+</ul>
+</dd>
+</dl>
+</div>
+</div>
+<div class="section" id="test-manager-execution">
+<h1>Test Manager: Execution</h1>
+</div>
+<div class="section" id="test-manager-scenarios">
+<h1>Test Manager: Scenarios</h1>
+<div class="section" id="testbox-signs-on-at-bootup">
+<h2>#1 - Testbox Signs On (At Bootup)</h2>
+<dl class="docutils">
+<dt>The testbox supplies a number of inputs when reporting for duty:</dt>
+<dd><ul class="first last simple">
+<li>IP address.</li>
+<li>System UUID.</li>
+<li>OS name.</li>
+<li>OS version.</li>
+<li>CPU architecture.</li>
+<li>CPU count (= threads).</li>
+<li>CPU VT-x/AMD-V capability.</li>
+<li>CPU nested paging capability.</li>
+<li>Chipset I/O MMU capability.</li>
+<li>Memory size.</li>
+<li>Scratch size space (for testing).</li>
+<li>Testbox Script revision.</li>
+</ul>
+</dd>
+<dt>Results:</dt>
+<dd><ul class="first last simple">
+<li>ACK or NACK.</li>
+<li>Testbox ID and name on ACK.</li>
+</ul>
+</dd>
+</dl>
+<p>After receiving a ACK the testbox will ask for work to do, i.e. continue with
+scenario #2. In the NACK case, it will sleep for 60 seconds and try again.</p>
+<p>Actions:</p>
+<ol class="arabic">
+<li><p class="first">Validate the testbox by looking the UUID up in the TestBoxes table.
+If not found, NACK the request. SQL:</p>
+<pre class="literal-block">
+SELECT idTestBox, sName
+FROM TestBoxes
+WHERE uuidSystem = :sUuid
+ AND tsExpire = 'infinity'::timestamp;
+</pre>
+</li>
+<li><p class="first">Check if any of the information by testbox script has changed. The two
+sizes are normalized first, memory size rounded to nearest 4 MB and scratch
+space is rounded down to nearest 64 MB. If anything changed, insert a new
+row in the testbox table and historize the current one, i.e. set
+OLD.tsExpire to NEW.tsEffective and get a new value for NEW.idGenTestBox.</p>
+</li>
+<li><dl class="first docutils">
+<dt>Check with TestBoxStatuses:</dt>
+<dd><ol class="first last loweralpha simple">
+<li>If there is an row for the testbox in it already clean up change it
+to 'idle' state and deal with any open testset like described in
+scenario #9.</li>
+<li>If there is no row, add one with 'idle' state.</li>
+</ol>
+</dd>
+</dl>
+</li>
+<li><p class="first">ACK the request and pass back the idTestBox.</p>
+</li>
+</ol>
+<dl class="docutils">
+<dt>Note! Testbox.enabled is not checked here, that is only relevant when it asks</dt>
+<dd>for a new task (scenario #2 and #5).</dd>
+<dt>Note! Should the testbox script detect changes in any of the inputs, it should</dt>
+<dd>redo the sign in.</dd>
+<dt>Note! In scenario #8, the box will not sign on until it has done the reboot and</dt>
+<dd>cleanup reporting!</dd>
+</dl>
+</div>
+<div class="section" id="testbox-asks-for-work-to-do">
+<h2>#2 - Testbox Asks For Work To Do</h2>
+<dl class="docutils">
+<dt>Inputs:</dt>
+<dd><ul class="first last simple">
+<li>The testbox is supplying its IP indirectly.</li>
+<li>The testbox should supply its UUID and ID directly.</li>
+</ul>
+</dd>
+<dt>Results:</dt>
+<dd><ul class="first last simple">
+<li>IDLE, WAIT, EXEC, REBOOT, UPGRADE, UPGRADE-AND-REBOOT, SPECIAL or DEAD.</li>
+</ul>
+</dd>
+</dl>
+<p>Actions:</p>
+<ol class="arabic">
+<li><p class="first">Validate the ID and IP by selecting the currently valid testbox row:</p>
+<pre class="literal-block">
+SELECT idGenTestBox, fEnabled, idSchedGroup, enmPendingCmd
+FROM TestBoxes
+WHERE id = :id
+ AND uuidSystem = :sUuid
+ AND ip = :ip
+ AND tsExpire = 'infinity'::timestamp;
+</pre>
+<p>If NOT found return DEAD to the testbox client (it will go back to sign on
+mode and retry every 60 seconds or so - see scenario #1).</p>
+<dl class="docutils">
+<dt>Note! The WUI will do all necessary clean-ups when deleting a testbox, so</dt>
+<dd><p class="first last">contrary to the initial plans, we don't need to do anything more for
+the DEAD status.</p>
+</dd>
+</dl>
+</li>
+<li><p class="first">Check with TestBoxStatuses (maybe joined with query from 1).</p>
+<p>If enmState is 'gang-gathering': Goto scenario #6 on timeout or pending
+'abort' or 'reboot' command. Otherwise, tell the testbox to WAIT [done].</p>
+<p>If enmState is 'gang-testing': The gang has been gathered and execution
+has been triggered. Goto 5.</p>
+<p>If enmState is not 'idle', change it to 'idle'.</p>
+<p>If idTestSet is not NULL, CALL scenario #9 to it up.</p>
+<p>If there is a pending abort command, remove it.</p>
+<p>If there is a pending command and the old state doesn't indicate that it was
+being executed, GOTO scenario #3.</p>
+<dl class="docutils">
+<dt>Note! There should be a TestBoxStatuses row after executing scenario #1,</dt>
+<dd><p class="first last">however should none be found for some funky reason, returning DEAD
+will fix the problem (see above)</p>
+</dd>
+</dl>
+</li>
+<li><p class="first">If the testbox was marked as disabled, respond with an IDLE command to the
+testbox [done]. (Note! Must do this after TestBoxStatuses maintenance from
+point 2, or abandoned tests won't be cleaned up after a testbox is disabled.)</p>
+</li>
+<li><p class="first">Consider testcases in the scheduling queue, pick the first one which the
+testbox can execute. There is a concurrency issue here, so we put and
+exclusive lock on the SchedQueues table while considering its content.</p>
+<p>The cursor we open looks something like this:</p>
+<pre class="literal-block">
+SELECT idItem, idGenTestCaseArgs,
+ idTestSetGangLeader, cMissingGangMembers
+FROM SchedQueues
+WHERE idSchedGroup = :idSchedGroup
+ AND ( bmHourlySchedule is NULL
+ OR get_bit(bmHourlySchedule, :iHourOfWeek) = 1 ) --&lt; does this work?
+ORDER BY ASC idItem;
+</pre>
+</li>
+</ol>
+<blockquote>
+<p>If there no rows are returned (this can happen because no testgroups are
+associated with this scheduling group, the scheduling group is disabled,
+or because the queue is being regenerated), we will tell the testbox to
+IDLE [done].</p>
+<dl class="docutils">
+<dt>For each returned row we will:</dt>
+<dd><ol class="first last loweralpha">
+<li><p class="first">Check testcase/group dependencies.</p>
+</li>
+<li><p class="first">Select a build (and default testsuite) satisfying the dependencies.</p>
+</li>
+<li><p class="first">Check the testcase requirements with that build in mind.</p>
+</li>
+<li><p class="first">If idTestSetGangLeader is NULL, try allocate the necessary resources.</p>
+</li>
+<li><p class="first">If it didn't check out, fetch the next row and redo from (a).</p>
+</li>
+<li><p class="first">Tentatively create a new test set row.</p>
+</li>
+<li><dl class="first docutils">
+<dt>If not gang scheduling:</dt>
+<dd><ul class="first last simple">
+<li>Next state: 'testing'</li>
+</ul>
+</dd>
+<dt>ElIf we're the last gang participant:</dt>
+<dd><ul class="first last simple">
+<li>Set idTestSetGangLeader to NULL.</li>
+<li>Set cMissingGangMembers to 0.</li>
+<li>Next state: 'gang-testing'</li>
+</ul>
+</dd>
+<dt>ElIf we're the first gang member:</dt>
+<dd><ul class="first last simple">
+<li>Set cMissingGangMembers to TestCaseArgs.cGangMembers - 1.</li>
+<li>Set idTestSetGangLeader to our idTestSet.</li>
+<li>Next state: 'gang-gathering'</li>
+</ul>
+</dd>
+<dt>Else:</dt>
+<dd><ul class="first last simple">
+<li>Decrement cMissingGangMembers.</li>
+<li>Next state: 'gang-gathering'</li>
+</ul>
+</dd>
+<dt>If we're not gang scheduling OR cMissingGangMembers is 0:</dt>
+<dd><p class="first last">Move the scheduler queue entry to the end of the queue.</p>
+</dd>
+</dl>
+<p>Update our TestBoxStatuses row with the new state and test set.
+COMMIT;</p>
+</li>
+</ol>
+</dd>
+</dl>
+</blockquote>
+<ol class="arabic" start="5">
+<li><dl class="first docutils">
+<dt>If state is 'testing' or 'gang-testing':</dt>
+<dd><p class="first">EXEC reponse.</p>
+<p class="last">The EXEC response for a gang scheduled testcase includes a number of
+extra arguments so that the script knows the position of the testbox
+it is running on and of the other members. This means the that the
+TestSet.iGangMemberNo is passed using --gang-member-no and the IP
+addresses of the all gang members using --gang-ipv4-&lt;memb-no&gt; &lt;ip&gt;.</p>
+</dd>
+<dt>Else (state is 'gang-gathering'):</dt>
+<dd><p class="first last">WAIT</p>
+</dd>
+</dl>
+</li>
+</ol>
+</div>
+<div class="section" id="pending-command-when-testbox-asks-for-work">
+<h2>#3 - Pending Command When Testbox Asks For Work</h2>
+<p>This is a subfunction of scenario #2 and #5.</p>
+<p>As seen in scenario #2, the testbox will send 'abort' commands to /dev/null
+when it finds one when not executing a test. This includes when it reports
+that the test has completed (no need to abort a completed test, wasting lot
+of effort when standing at the finish line).</p>
+<p>The other commands, though, are passed back to the testbox. The testbox
+script will respond with an ACK or NACK as it sees fit. If NACKed, the
+pending command will be removed (pending_cmd set to none) and that's it.
+If ACKed, the state of the testbox will change to that appropriate for the
+command and the pending_cmd set to none. Should the testbox script fail to
+respond, the command will be repeated the next time it asks for work.</p>
+</div>
+<div class="section" id="testbox-uploads-results-during-test">
+<h2>#4 - Testbox Uploads Results During Test</h2>
+<p>TODO</p>
+</div>
+<div class="section" id="testbox-completes-test-and-asks-for-work">
+<h2>#5 - Testbox Completes Test and Asks For Work</h2>
+<p>This is very similar to scenario #2</p>
+<p>TODO</p>
+</div>
+<div class="section" id="gang-gathering-timeout">
+<h2>#6 - Gang Gathering Timeout</h2>
+<p>This is a subfunction of scenario #2.</p>
+<p>When gathering a gang of testboxes for a testcase, we do not want to wait
+forever and have testboxes doing nothing for hours while waiting for partners.
+So, the gathering has a reasonable timeout (imagine something like 20-30 mins).</p>
+<p>Also, we need some way of dealing with 'abort' and 'reboot' commands being
+issued while waiting. The easy way out is pretend it's a time out.</p>
+<p>When changing the status to 'gang-timeout' we have to be careful. First of all,
+we need to exclusively lock the SchedQueues and TestBoxStatuses (in that order)
+and re-query our status. If it changed redo the checks in scenario #2 point 2.</p>
+<p>If we still want to timeout/abort, change the state from 'gang-gathering' to
+'gang-gathering-timedout' on all the gang members that has gathered so far.
+Then reset the scheduling queue record and move it to the end of the queue.</p>
+<p>When acting on 'gang-timeout' the TM will fail the testset in a manner similar
+to scenario #9. No need to repeat that.</p>
+</div>
+<div class="section" id="gang-cleanup">
+<h2>#7 - Gang Cleanup</h2>
+<p>When a testbox completes a gang scheduled test, we will have to serialize
+resource cleanup (both globally and on testboxes) as they stop. More details
+can be found in the documentation of 'gang-cleanup'.</p>
+<p>So, the transition from 'gang-testing' is always to 'gang-cleanup'. When we
+can safely leave 'gang-cleanup' is decided by the query:</p>
+<pre class="literal-block">
+SELECT COUNT(*)
+FROM TestBoxStatuses,
+ TestSets
+WHERE TestSets.idTestSetGangLeader = :idTestSetGangLeader
+ AND TestSets.idTestBox = TestBoxStatuses.idTestBox
+ AND TestBoxStatuses.enmState = 'gang-running'::TestBoxState_T;
+</pre>
+<p>As long as there are testboxes still running, we stay in the 'gang-cleanup'
+state. Once there are none, we continue closing the testset and such.</p>
+</div>
+<div class="section" id="testbox-reports-a-crash-during-test-execution">
+<h2>#8 - Testbox Reports A Crash During Test Execution</h2>
+<p>TODO</p>
+</div>
+<div class="section" id="cleaning-up-abandoned-testcase">
+<h2>#9 - Cleaning Up Abandoned Testcase</h2>
+<p>This is a subfunction of scenario #1 and #2. The actions taken are the same in
+both situations. The precondition for taking this path is that the row in the
+testboxstatus table is referring to a testset (i.e. testset_id is not NULL).</p>
+<p>Actions:</p>
+<ol class="arabic simple">
+<li><dl class="first docutils">
+<dt>If the testset is incomplete, we need to completed:</dt>
+<dd><ol class="first last loweralpha">
+<li>Add a message to the root TestResults row, creating one if necessary,
+that explains that the test was abandoned. This is done
+by inserting/finding the string into/in TestResultStrTab and adding
+a row to TestResultMsgs with idStrMsg set to that string id and
+enmLevel set to 'failure'.</li>
+<li>Mark the testset as failed.</li>
+</ol>
+</dd>
+</dl>
+</li>
+<li>Free any global resources referenced by the test set. This is done by
+deleting all rows in GlobalResourceStatuses matching the testbox id.</li>
+<li>Set the idTestSet to NULL in the TestBoxStatuses row.</li>
+</ol>
+</div>
+<div class="section" id="cleaning-up-a-disabled-dead-testbox">
+<h2>#10 - Cleaning Up a Disabled/Dead TestBox</h2>
+<p>The UI needs to be able to clean up the remains of a testbox which for some
+reason is out of action. Normal cleaning up of abandoned testcases requires
+that the testbox signs on or asks for work, but if the testbox is dead or
+in some way indisposed, it won't be doing any of that. So, the testbox
+sheriff needs to have a way of cleaning up after it.</p>
+<p>It's basically a manual scenario #9 but with some safe guards, like checking
+that the box hasn't been active for the last 1-2 mins (max idle/wait time * 2).</p>
+<dl class="docutils">
+<dt>Note! When disabling a box that still executing the testbox script, this</dt>
+<dd>cleanup isn't necessary as it will happen automatically. Also, it's
+probably desirable that the testbox finishes what ever it is doing first
+before going dormant.</dd>
+</dl>
+</div>
+</div>
+<div class="section" id="test-manager-analysis">
+<h1>Test Manager: Analysis</h1>
+<p>One of the testbox sheriff's tasks is to try figure out the reason why something
+failed. The test manager will provide facilities for doing so from very early
+in it's implementation.</p>
+<p>We need to work out some useful status reports for the early implementation.
+Later there will be more advanced analysis tools, where for instance we can
+create graphs from selected test result values or test execution times.</p>
+</div>
+<div class="section" id="implementation-plan">
+<h1>Implementation Plan</h1>
+<p>This has changed for various reasons. The current plan is to implement the
+infrastructure (TM &amp; testbox script) first and do a small deployment with the
+2-5 test drivers in the Testsuite as basis. Once the bugs are worked out, we
+will convert the rest of the tests and start adding new ones.</p>
+<p>We just need to finally get this done, no point in doing it piecemeal by now!</p>
+<div class="section" id="test-manager-implementation-sub-tasks">
+<h2>Test Manager Implementation Sub-Tasks</h2>
+<p>The implementation of the test manager and adjusting/completing of the testbox
+script and the test drivers are tasks which can be done by more than one
+person. Splitting up the TM implementation into smaller tasks should allow
+parallel development of different tasks and get us working code sooner.</p>
+</div>
+<div class="section" id="milestone-1">
+<h2>Milestone #1</h2>
+<p>The goal is to getting the fundamental testmanager engine implemented, debugged
+and working. With the exception of testboxes, the configuration will be done
+via SQL inserts.</p>
+<p>Tasks in somewhat prioritized order:</p>
+<blockquote>
+<ul class="simple">
+<li>Kick off test manager. It will live in testmanager/. Salvage as much as
+possible from att/testserv. Create basic source and file layout.</li>
+<li>Adjust the testbox script, part one. There currently is a testbox script
+in att/testbox, this shall be moved up into testboxscript/. The script
+needs to be adjusted according to the specification layed down earlier
+in this document. Installers or installation scripts for all relevant
+host OSes are required. Left for part two is result reporting beyond the
+primary log. This task must be 100% feature complete, on all host OSes,
+there is no room for FIXME, XXX or &#64;todo here.</li>
+<li>Implement the schedule queue generator.</li>
+<li>Implement the testbox dispatcher in TM. Support all the testbox script
+responses implemented above, including upgrading the testbox script.</li>
+<li>Implement simple testbox management page.</li>
+<li>Implement some basic activity and result reports so that we can see
+what's going on.</li>
+<li>Create a testmanager / testbox test setup. This lives in selftest/.<ol class="arabic">
+<li>Set up something that runs, no fiddly bits. Debug till it works.</li>
+<li>Create a setup that tests testgroup dependencies, i.e. real tests
+depending on smoke tests.</li>
+<li>Create a setup that exercises testcase dependency.</li>
+<li>Create a setup that exercises global resource allocation.</li>
+<li>Create a setup that exercises gang scheduling.</li>
+</ol>
+</li>
+<li>Check that all features work.</li>
+</ul>
+</blockquote>
+</div>
+<div class="section" id="milestone-2">
+<h2>Milestone #2</h2>
+<p>The goal is getting to VBox testing.</p>
+<p>Tasks in somewhat prioritized order:</p>
+<blockquote>
+<ul class="simple">
+<li>Implement full result reporting in the testbox script and testbox driver.
+A testbox script specific reporter needs to be implemented for the
+testdriver framework. The testbox script needs to forward the results to
+the test manager, or alternatively the testdriver report can talk
+directly to the TM.</li>
+<li>Implement the test manager side of the test result reporting.</li>
+<li>Extend the selftest with some setup that report all kinds of test
+results.</li>
+<li>Implement script/whatever feeding builds to the test manager from the
+tinderboxes.</li>
+<li>The toplevel test driver is a VBox thing that must be derived from the
+base TestDriver class or maybe the VBox one. It should move from
+toptestdriver to testdriver and be renamed to vboxtltd or smth.</li>
+<li>Create a vbox testdriver that boots the t-xppro VM once and that's it.</li>
+<li>Create a selftest setup which tests booting t-xppro taking builds from
+the tinderbox.</li>
+</ul>
+</blockquote>
+</div>
+<div class="section" id="milestone-3">
+<h2>Milestone #3</h2>
+<p>The goal for this milestone is configuration and converting current testcases,
+the result will be the a minimal test deployment (4-5 new testboxes).</p>
+<p>Tasks in somewhat prioritized order:</p>
+<blockquote>
+<ul class="simple">
+<li>Implement testcase configuration.</li>
+<li>Implement testgroup configuration.</li>
+<li>Implement build source configuration.</li>
+<li>Implement scheduling group configuration.</li>
+<li>Implement global resource configuration.</li>
+<li>Re-visit the testbox configuration.</li>
+<li>Black listing of builds.</li>
+<li>Implement simple failure analysis and reporting.</li>
+<li>Implement the initial smoke tests modelled on the current smoke tests.</li>
+<li>Implement installation tests for Windows guests.</li>
+<li>Implement installation tests for Linux guests.</li>
+<li>Implement installation tests for Solaris guest.</li>
+<li>Implement installation tests for OS/2 guest.</li>
+<li>Set up a small test deployment.</li>
+</ul>
+</blockquote>
+</div>
+<div class="section" id="further-work">
+<h2>Further work</h2>
+<p>After milestone #3 has been reached and issues found by the other team members
+have been addressed, we will probably go for full deployment.</p>
+<p>Beyond this point we will need to improve reporting and analysis. There may be
+configuration aspects needing reporting as well.</p>
+<p>Once deployed, a golden rule will be that all new features shall have test
+coverage. Preferably, implemented by someone else and prior to the feature
+implementation.</p>
+</div>
+</div>
+<div class="section" id="discussion-logs">
+<h1>Discussion Logs</h1>
+<div class="section" id="various-discussions-with-michal-and-or-klaus">
+<h2>2009-07-21,22,23 Various Discussions with Michal and/or Klaus</h2>
+<ul class="simple">
+<li>Scheduling of tests requiring more than one testbox.</li>
+<li>Scheduling of tests that cannot be executing concurrently on several machines
+because of some global resource like an iSCSI target.</li>
+<li>Manually create the test config permutations instead of having the test
+manager create all possible ones and wasting time.</li>
+<li>Distinguish between built types so we can run smoke tests on strick builds as
+well as release ones.</li>
+</ul>
+</div>
+<div class="section" id="brief-discussion-with-michal">
+<h2>2009-07-20 Brief Discussion with Michal</h2>
+<ul class="simple">
+<li>Installer for the testbox script to make bringing up a new testbox even
+smoother.</li>
+</ul>
+</div>
+<div class="section" id="raw-input">
+<h2>2009-07-16 Raw Input</h2>
+<ul class="simple">
+<li><dl class="first docutils">
+<dt>test set. recursive collection of:</dt>
+<dd><ul class="first last">
+<li>hierachical subtest name (slash sep)</li>
+<li>test parameters / config</li>
+<li>bool fail/succ</li>
+<li>attributes (typed?)</li>
+<li>test time</li>
+<li>e.g. throughput</li>
+<li>subresults</li>
+<li>log</li>
+<li>screenshots,....</li>
+</ul>
+</dd>
+</dl>
+</li>
+<li>client package (zip) dl from server (maybe client caching)</li>
+<li><dl class="first docutils">
+<dt>thoughts on bits to do at once.</dt>
+<dd><ul class="first last">
+<li>We <em>really</em> need the basic bits ASAP.</li>
+<li>client -&gt; support for test driver</li>
+<li>server -&gt; controls configs</li>
+<li>cleanup on both sides</li>
+</ul>
+</dd>
+</dl>
+</li>
+</ul>
+</div>
+<div class="section" id="raw-input-1">
+<h2>2009-07-15 Raw Input</h2>
+<ul class="simple">
+<li>testing should start automatically</li>
+<li>switching to branch too tedious</li>
+<li>useful to be able to partition testboxes (run specific builds on some boxes, let an engineer have a few boxes for a while).</li>
+<li>test specification needs to be more flexible (select tests, disable test, test scheduling (run certain tests nightly), ... )</li>
+<li>testcase dependencies (blacklisting builds, run smoketests on box A before long tests on box B, ...)</li>
+<li>more testing flexibility, more test than just install/moke. For instance unit tests, benchmarks, ...</li>
+<li>presentation/analysis: graphs!, categorize bugs, columns reorganizing grouped by test (hierarchical), overviews, result for last day.</li>
+<li>testcase specificion, variables (e.g. I/O-APIC, SMP, HWVIRT, SATA...) as sub-tests</li>
+<li>interation with ILOM/...: reset systems</li>
+<li>Changes needs LDAP authentication</li>
+<li>historize all configuration w/ name</li>
+<li>ability to run testcase locally (provided the VDI/ISO/whatever extra requirements can be met).</li>
+</ul>
+<hr class="docutils" />
+<table class="docutils footnote" frame="void" id="footnote-1" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label">[1]</td><td>no such footnote</td></tr>
+</tbody>
+</table>
+<hr class="docutils" />
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field"><th class="field-name">Status:</th><td class="field-body">$Id: AutomaticTestingRevamp.html $</td>
+</tr>
+<tr class="field"><th class="field-name">Copyright:</th><td class="field-body">Copyright (C) 2010-2023 Oracle Corporation.</td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+</div>
+</body>
+</html>