Index: trunk/src/VBox/ValidationKit/utils/audio/vkat.cpp
===================================================================
--- trunk/src/VBox/ValidationKit/utils/audio/vkat.cpp	(revision 89545)
+++ trunk/src/VBox/ValidationKit/utils/audio/vkat.cpp	(revision 89575)
@@ -139,6 +139,8 @@
     VKAT_TEST_OPT_COUNT = 900,
     VKAT_TEST_OPT_DEV,
-    VKAT_TEST_OPT_ATS_ADDR,
-    VKAT_TEST_OPT_ATS_PORT,
+    VKAT_TEST_OPT_GUEST_ATS_ADDR,
+    VKAT_TEST_OPT_GUEST_ATS_PORT,
+    VKAT_TEST_OPT_HOST_ATS_ADDR,
+    VKAT_TEST_OPT_HOST_ATS_PORT,
     VKAT_TEST_OPT_MODE,
     VKAT_TEST_OPT_OUTDIR,
@@ -188,23 +190,25 @@
 static const RTGETOPTDEF g_aCmdTestOptions[] =
 {
-    { "--backend",          'b',                          RTGETOPT_REQ_STRING  },
-    { "--drvaudio",         'd',                          RTGETOPT_REQ_NOTHING },
-    { "--exclude",          'e',                          RTGETOPT_REQ_UINT32  },
-    { "--exclude-all",      'a',                          RTGETOPT_REQ_NOTHING },
-    { "--mode",             VKAT_TEST_OPT_MODE,           RTGETOPT_REQ_STRING  },
-    { "--ats-address",      VKAT_TEST_OPT_ATS_ADDR,       RTGETOPT_REQ_STRING  },
-    { "--ats-port",         VKAT_TEST_OPT_ATS_PORT,       RTGETOPT_REQ_UINT32  },
-    { "--include",          'i',                          RTGETOPT_REQ_UINT32  },
-    { "--outdir",           VKAT_TEST_OPT_OUTDIR,         RTGETOPT_REQ_STRING  },
-    { "--count",            VKAT_TEST_OPT_COUNT,          RTGETOPT_REQ_UINT32  },
-    { "--device",           VKAT_TEST_OPT_DEV,            RTGETOPT_REQ_STRING  },
-    { "--pause",            VKAT_TEST_OPT_PAUSE,          RTGETOPT_REQ_UINT32  },
-    { "--pcm-bit",          VKAT_TEST_OPT_PCM_BIT,        RTGETOPT_REQ_UINT8   },
-    { "--pcm-chan",         VKAT_TEST_OPT_PCM_CHAN,       RTGETOPT_REQ_UINT8   },
-    { "--pcm-hz",           VKAT_TEST_OPT_PCM_HZ,         RTGETOPT_REQ_UINT16  },
-    { "--pcm-signed",       VKAT_TEST_OPT_PCM_SIGNED,     RTGETOPT_REQ_BOOL    },
-    { "--tag",              VKAT_TEST_OPT_TAG,            RTGETOPT_REQ_STRING  },
-    { "--tempdir",          VKAT_TEST_OPT_TEMPDIR,        RTGETOPT_REQ_STRING  },
-    { "--volume",           VKAT_TEST_OPT_VOL,            RTGETOPT_REQ_UINT8   }
+    { "--backend",           'b',                          RTGETOPT_REQ_STRING  },
+    { "--drvaudio",          'd',                          RTGETOPT_REQ_NOTHING },
+    { "--exclude",           'e',                          RTGETOPT_REQ_UINT32  },
+    { "--exclude-all",       'a',                          RTGETOPT_REQ_NOTHING },
+    { "--mode",              VKAT_TEST_OPT_MODE,           RTGETOPT_REQ_STRING  },
+    { "--guest-ats-address", VKAT_TEST_OPT_GUEST_ATS_ADDR, RTGETOPT_REQ_STRING  },
+    { "--guest-ats-port",    VKAT_TEST_OPT_GUEST_ATS_PORT, RTGETOPT_REQ_UINT32  },
+    { "--host-ats-address",  VKAT_TEST_OPT_HOST_ATS_ADDR,  RTGETOPT_REQ_STRING  },
+    { "--host-ats-port",     VKAT_TEST_OPT_HOST_ATS_PORT,  RTGETOPT_REQ_UINT32  },
+    { "--include",           'i',                          RTGETOPT_REQ_UINT32  },
+    { "--outdir",            VKAT_TEST_OPT_OUTDIR,         RTGETOPT_REQ_STRING  },
+    { "--count",             VKAT_TEST_OPT_COUNT,          RTGETOPT_REQ_UINT32  },
+    { "--device",            VKAT_TEST_OPT_DEV,            RTGETOPT_REQ_STRING  },
+    { "--pause",             VKAT_TEST_OPT_PAUSE,          RTGETOPT_REQ_UINT32  },
+    { "--pcm-bit",           VKAT_TEST_OPT_PCM_BIT,        RTGETOPT_REQ_UINT8   },
+    { "--pcm-chan",          VKAT_TEST_OPT_PCM_CHAN,       RTGETOPT_REQ_UINT8   },
+    { "--pcm-hz",            VKAT_TEST_OPT_PCM_HZ,         RTGETOPT_REQ_UINT16  },
+    { "--pcm-signed",        VKAT_TEST_OPT_PCM_SIGNED,     RTGETOPT_REQ_BOOL    },
+    { "--tag",               VKAT_TEST_OPT_TAG,            RTGETOPT_REQ_STRING  },
+    { "--tempdir",           VKAT_TEST_OPT_TEMPDIR,        RTGETOPT_REQ_STRING  },
+    { "--volume",            VKAT_TEST_OPT_VOL,            RTGETOPT_REQ_UINT8   }
 };
 
@@ -306,21 +310,8 @@
         AudioTestToneParamsInitRandom(&pTstParms->TestTone, &pTstParms->Props);
 
-        PAUDIOTESTENTRY pTst;
-        rc = AudioTestSetTestBegin(&pTstEnv->Set, "Playing test tone", pTstParms, &pTst);
+        PAUDIOTESTTONEPARMS const pToneParms = &pTstParms->TestTone;
+        rc = AudioTestSvcClientToneRecord(&pTstEnv->u.Host.AtsClValKit, pToneParms);
         if (RT_SUCCESS(rc))
-        {
-            PDMAUDIOSTREAMCFG Cfg;
-            RT_ZERO(Cfg);
-            /** @todo Add more parameters here? */
-            Cfg.Props = pTstParms->Props;
-
-            rc = AudioTestSvcClientTonePlay(&pTstEnv->u.Host.AtsClGuest, &pTstParms->TestTone);
-            if (RT_SUCCESS(rc))
-            {
-                AudioTestSetTestDone(pTst);
-            }
-            else
-                AudioTestSetTestFailed(pTst, rc, "Playing test tone failed");
-        }
+            rc = AudioTestSvcClientTonePlay(&pTstEnv->u.Host.AtsClGuest, pToneParms);
 
         if (RT_FAILURE(rc))
@@ -346,5 +337,5 @@
 static DECLCALLBACK(int) audioTestRecordToneSetup(PAUDIOTESTENV pTstEnv, PAUDIOTESTDESC pTstDesc, PAUDIOTESTPARMS pTstParmsAcq, void **ppvCtx)
 {
-    RT_NOREF(pTstDesc, ppvCtx);
+    RT_NOREF(pTstEnv, pTstDesc, ppvCtx);
 
     pTstParmsAcq->enmType     = AUDIOTESTTYPE_TESTTONE_RECORD;
@@ -360,16 +351,5 @@
     pTstParmsAcq->idxCurrent  = 0;
 
-    /* Connect to the Validation Kit audio driver ATS. */
-    int rc = AudioTestSvcClientConnect(&pTstEnv->u.Host.AtsClValKit,
-                                       "127.0.0.1" /** @todo Make this dynamic. */, ATS_TCP_DEFAULT_PORT);
-    if (RT_SUCCESS(rc))
-    {
-        char szTag[AUDIOTEST_TAG_MAX];
-        rc = RTStrPrintf2(szTag, sizeof(szTag), "%s-valkit", pTstEnv->szTag);
-        if (RT_SUCCESS(rc))
-            rc = AudioTestSvcClientTestSetBegin(&pTstEnv->u.Host.AtsClValKit, szTag);
-    }
-
-    return rc;
+    return VINF_SUCCESS;
 }
 
@@ -391,25 +371,14 @@
         pTstParms->TestTone.msDuration = RTRandU32Ex(50 /* ms */, RT_MS_30SEC); /** @todo Record even longer? */
 #endif
-        PAUDIOTESTENTRY pTst;
-        rc = AudioTestSetTestBegin(&pTstEnv->Set, "Recording test tone", pTstParms, &pTst);
+        /*
+         * 1. Arm the ValKit ATS with the recording parameters.
+         */
+        rc = AudioTestSvcClientTonePlay(&pTstEnv->u.Host.AtsClValKit, &pTstParms->TestTone);
         if (RT_SUCCESS(rc))
         {
             /*
-             * 1. Arm the ValKit ATS with the recording parameters.
+             * 2. Tell the guest ATS to start recording.
              */
-            rc = AudioTestSvcClientTonePlay(&pTstEnv->u.Host.AtsClValKit, &pTstParms->TestTone);
-            if (RT_SUCCESS(rc))
-            {
-                /*
-                 * 2. Tell the guest ATS to start recording.
-                 */
-                rc = AudioTestSvcClientToneRecord(&pTstEnv->u.Host.AtsClGuest, &pTstParms->TestTone);
-                if (RT_SUCCESS(rc))
-                {
-                    AudioTestSetTestDone(pTst);
-                }
-                else
-                    AudioTestSetTestFailed(pTst, rc, "Recording test tone failed");
-            }
+            rc = AudioTestSvcClientToneRecord(&pTstEnv->u.Host.AtsClGuest, &pTstParms->TestTone);
         }
 
@@ -426,16 +395,7 @@
 static DECLCALLBACK(int) audioTestRecordToneDestroy(PAUDIOTESTENV pTstEnv, void *pvCtx)
 {
-    RT_NOREF(pvCtx);
-
-    char szTag[AUDIOTEST_TAG_MAX];
-    int rc = RTStrPrintf2(szTag, sizeof(szTag), "%s-valkit", pTstEnv->szTag);
-    if (RT_SUCCESS(rc))
-        rc = AudioTestSvcClientTestSetEnd(&pTstEnv->u.Host.AtsClValKit, szTag);
-
-    int rc2 = AudioTestSvcClientClose(&pTstEnv->u.Host.AtsClValKit);
-    if (RT_SUCCESS(rc))
-        rc = rc2;
-
-    return rc;
+    RT_NOREF(pTstEnv, pvCtx);
+
+    return VINF_SUCCESS;
 }
 
@@ -550,36 +510,42 @@
     else if (pTstEnv->enmMode == AUDIOTESTMODE_HOST)
     {
-        /* Generate tag for the host side. */
-        char szTag[AUDIOTEST_TAG_MAX];
-        rc = RTStrPrintf2(szTag, sizeof(szTag), "%s-host", pTstEnv->szTag);
+        /* Generate tags for the host and guest side. */
+        char szTagHost [AUDIOTEST_TAG_MAX];
+        char szTagGuest[AUDIOTEST_TAG_MAX];
+
+        rc = RTStrPrintf2(szTagHost, sizeof(szTagHost),   "%s-host",  pTstEnv->szTag);
         AssertRCReturn(rc, rc);
-
-        /* We have one single test set for all executed tests for now. */
-        rc = AudioTestSetCreate(&pTstEnv->Set, pTstEnv->szPathTemp, szTag);
+        rc = RTStrPrintf2(szTagGuest, sizeof(szTagGuest), "%s-guest", pTstEnv->szTag);
+        AssertRCReturn(rc, rc);
+
+        RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Guest test set tag is '%s'\n", szTagGuest);
+        RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Host test set tag is '%s'\n", szTagHost);
+
+        rc = AudioTestSvcClientTestSetBegin(&pTstEnv->u.Host.AtsClValKit, szTagHost);
+        if (RT_SUCCESS(rc))
+            rc = AudioTestSvcClientTestSetBegin(&pTstEnv->u.Host.AtsClGuest, szTagGuest);
+
         if (RT_SUCCESS(rc))
         {
-            rc = AudioTestSvcClientTestSetBegin(&pTstEnv->u.Host.AtsClGuest, pTstEnv->szTag);
-            if (RT_SUCCESS(rc))
+            unsigned uSeq = 0;
+            for (unsigned i = 0; i < RT_ELEMENTS(g_aTests); i++)
             {
-                unsigned uSeq = 0;
-                for (unsigned i = 0; i < RT_ELEMENTS(g_aTests); i++)
-                {
-                    int rc2 = audioTestOne(pTstEnv, &g_aTests[i], uSeq, pOverrideParms);
-                    if (RT_SUCCESS(rc))
-                        rc = rc2;
-
-                    if (!g_aTests[i].fExcluded)
-                        uSeq++;
-
-                    if (g_fTerminate)
-                        break;
-                }
-
-                int rc2 = AudioTestSvcClientTestSetEnd(&pTstEnv->u.Host.AtsClGuest, pTstEnv->szTag);
+                int rc2 = audioTestOne(pTstEnv, &g_aTests[i], uSeq, pOverrideParms);
                 if (RT_SUCCESS(rc))
                     rc = rc2;
+
+                if (!g_aTests[i].fExcluded)
+                    uSeq++;
+
+                if (g_fTerminate)
+                    break;
             }
 
-            audioTestEnvPrologue(pTstEnv);
+            int rc2 = AudioTestSvcClientTestSetEnd(&pTstEnv->u.Host.AtsClGuest, szTagGuest);
+            if (RT_SUCCESS(rc))
+                rc = rc2;
+            rc2 = AudioTestSvcClientTestSetEnd(&pTstEnv->u.Host.AtsClValKit, szTagHost);
+            if (RT_SUCCESS(rc))
+                rc = rc2;
         }
     }
@@ -598,12 +564,14 @@
     switch (pOpt->iShort)
     {
-        case 'd':                    return "Go via DrvAudio instead of directly interfacing with the backend";
-        case VKAT_TEST_OPT_DEV:      return "Use the specified audio device";
-        case VKAT_TEST_OPT_ATS_ADDR: return "ATS address (hostname or IP) to connect to";
-        case VKAT_TEST_OPT_ATS_PORT: return "ATS port to connect to. Defaults to 6052 if not set";
-        case VKAT_TEST_OPT_MODE:     return "Specifies the mode this program runs at";
-        case 'e':                    return "Exclude the given test id from the list";
-        case 'a':                    return "Exclude all tests from the list (useful to enable single tests later with --include)";
-        case 'i':                    return "Include the given test id in the list";
+        case 'd':                          return "Go via DrvAudio instead of directly interfacing with the backend";
+        case VKAT_TEST_OPT_DEV:            return "Use the specified audio device";
+        case VKAT_TEST_OPT_GUEST_ATS_ADDR: return "Address of guest ATS to connect to.";
+        case VKAT_TEST_OPT_GUEST_ATS_PORT: return "Port of guest ATS to connect to [6052].";
+        case VKAT_TEST_OPT_HOST_ATS_ADDR:  return "Address of host ATS to connect to.";
+        case VKAT_TEST_OPT_HOST_ATS_PORT:  return "Port of host ATS to connect to [6052].";
+        case VKAT_TEST_OPT_MODE:           return "Specifies the mode this program runs at";
+        case 'e':                          return "Exclude the given test id from the list";
+        case 'a':                          return "Exclude all tests from the list (useful to enable single tests later with --include)";
+        case 'i':                          return "Include the given test id in the list";
     }
     return NULL;
@@ -632,6 +600,9 @@
     uint32_t    uPcmHz        = 0;
     bool        fPcmSigned    = true;
-    const char *pszTcpAddr    = NULL;
-    uint16_t    uTcpPort      = 0;
+
+    const char *pszGuestTcpAddr  = NULL;
+    uint16_t    uGuestTcpPort    = ATS_TCP_GUEST_DEFAULT_PORT;
+    const char *pszValKitTcpAddr = NULL;
+    uint16_t    uValKitTcpPort   = ATS_TCP_HOST_DEFAULT_PORT;
 
     int           rc;
@@ -662,14 +633,18 @@
                 break;
 
-            case VKAT_TEST_OPT_ATS_ADDR:
-                if (TstEnv.enmMode == AUDIOTESTMODE_UNKNOWN)
-                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Must specify a test mode first!");
-                pszTcpAddr = ValueUnion.psz;
-                break;
-
-            case VKAT_TEST_OPT_ATS_PORT:
-                if (TstEnv.enmMode == AUDIOTESTMODE_UNKNOWN)
-                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Must specify a test mode first!");
-                uTcpPort = ValueUnion.u32;
+            case VKAT_TEST_OPT_GUEST_ATS_ADDR:
+                pszGuestTcpAddr = ValueUnion.psz;
+                break;
+
+            case VKAT_TEST_OPT_GUEST_ATS_PORT:
+                uGuestTcpPort = ValueUnion.u32;
+                break;
+
+            case VKAT_TEST_OPT_HOST_ATS_ADDR:
+                pszValKitTcpAddr = ValueUnion.psz;
+                break;
+
+            case VKAT_TEST_OPT_HOST_ATS_PORT:
+                uValKitTcpPort = ValueUnion.u32;
                 break;
 
@@ -754,14 +729,12 @@
     if (TstEnv.enmMode == AUDIOTESTMODE_HOST)
     {
-        /* Use the default port is none is specified. */
-        if (!uTcpPort)
-            uTcpPort = ATS_TCP_DEFAULT_PORT;
-
-        if (!pszTcpAddr)
-            return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--ats-address missing\n");
+        if (!pszGuestTcpAddr)
+            return RTMsgErrorExit(RTEXITCODE_SYNTAX, "--guest-ats-address missing\n");
     }
 
     /* For now all tests have the same test environment. */
-    rc = audioTestEnvInit(&TstEnv, pDrvReg, fWithDrvAudio, pszTcpAddr, uTcpPort);
+    rc = audioTestEnvInit(&TstEnv, pDrvReg, fWithDrvAudio,
+                          pszValKitTcpAddr, uValKitTcpPort,
+                          pszGuestTcpAddr, uGuestTcpPort);
     if (RT_SUCCESS(rc))
     {
Index: trunk/src/VBox/ValidationKit/utils/audio/vkatCmdSelfTest.cpp
===================================================================
--- trunk/src/VBox/ValidationKit/utils/audio/vkatCmdSelfTest.cpp	(revision 89545)
+++ trunk/src/VBox/ValidationKit/utils/audio/vkatCmdSelfTest.cpp	(revision 89575)
@@ -44,4 +44,11 @@
 
 
+/**
+ * Thread callback for mocking the guest (VM) side of things.
+ *
+ * @returns VBox status code.
+ * @param   hThread             Thread handle.
+ * @param   pvUser              Pointer to user-supplied data.
+ */
 static DECLCALLBACK(int) audioTestSelftestGuestAtsThread(RTTHREAD hThread, void *pvUser)
 {
@@ -73,8 +80,7 @@
                       2 /* 16-bit */, true  /* fSigned */, 2 /* cChannels */, 44100 /* uHz */);
 
-    /* Use ATS_ALT_PORT, as on ATS_DEFAULT_PORT the
-     * Validation Kit audio driver ATS already is running on ATS_DEFAULT_PORT. */
-    rc = audioTestEnvInit(pTstEnv, pCtx->Guest.pDrvReg, pCtx->fWithDrvAudio,
-                          "127.0.0.1", ATS_TCP_ALT_PORT);
+    rc = audioTestEnvInit(pTstEnv, pTstEnv->DrvStack.pDrvReg, pCtx->fWithDrvAudio,
+                          pCtx->Host.szValKitAtsAddr, pCtx->Host.uValKitAtsPort,
+                          pCtx->Guest.szAtsAddr, pCtx->Guest.uAtsPort);
     if (RT_SUCCESS(rc))
     {
@@ -102,8 +108,11 @@
     /*
      * The self-test does the following:
-     * - 1. Creates an ATS instance to emulate the guest mode ("--mode guest")
-     *      at port 6042 (ATS_ALT_PORT).
+     * - 1. a) Creates an ATS instance to emulate the guest mode ("--mode guest")
+     *         at port 6042 (ATS_TCP_GUEST_DEFAULT_PORT).
+     *      or
+     *      b) Connect to an already existing guest ATS instance if "--guest-ats-address" is specified.
+     *      This makes it more flexible in terms of testing / debugging.
      * - 2. Uses the Validation Kit audio backend, which in turn creates an ATS instance
-     *      at port 6052 (ATS_DEFAULT_PORT).
+     *      at port 6052 (ATS_TCP_HOST_DEFAULT_PORT).
      * - 3. Executes a complete test run locally (e.g. without any guest (VM) involved).
      */
@@ -125,5 +134,5 @@
     AssertRCReturn(rc, RTEXITCODE_FAILURE);
 
-    rc = AudioTestPathCreateTemp(pTstEnv->szPathTemp, sizeof(pTstEnv->szPathTemp), "selftest-host");
+    rc = AudioTestPathCreateTemp(pTstEnv->szPathTemp, sizeof(pTstEnv->szPathTemp), "selftest-tmp");
     AssertRCReturn(rc, RTEXITCODE_FAILURE);
 
@@ -133,29 +142,32 @@
     /*
      * Step 1.
-     * Creates a separate thread for the guest ATS.
      */
-    RTTHREAD hThreadGstAts;
-    rc = RTThreadCreate(&hThreadGstAts, audioTestSelftestGuestAtsThread, pCtx, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE,
-                        "VKATGstAts");
+    RTTHREAD hThreadGstAts = NIL_RTTHREAD;
+
+    bool const fStartGuestAts = RTStrNLen(pCtx->Host.szGuestAtsAddr, sizeof(pCtx->Host.szGuestAtsAddr)) == 0;
+    if (fStartGuestAts)
+    {
+        /* Step 1b. */
+        rc = RTThreadCreate(&hThreadGstAts, audioTestSelftestGuestAtsThread, pCtx, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE,
+                            "VKATGstAts");
+        if (RT_SUCCESS(rc))
+            rc = RTThreadUserWait(hThreadGstAts, RT_MS_30SEC);
+    }
+    /* else Step 1a later. */
+
     if (RT_SUCCESS(rc))
     {
-        rc = RTThreadUserWait(hThreadGstAts, RT_MS_30SEC);
+        /*
+         * Steps 2 + 3.
+         */
+        pTstEnv->enmMode = AUDIOTESTMODE_HOST;
+
+        rc = audioTestEnvInit(pTstEnv, &g_DrvHostValidationKitAudio, true /* fWithDrvAudio */,
+                              pCtx->Host.szValKitAtsAddr, pCtx->Host.uValKitAtsPort,
+                              pCtx->Host.szGuestAtsAddr, pCtx->Host.uGuestAtsPort);
         if (RT_SUCCESS(rc))
         {
-            /*
-             * Steps 2 + 3.
-             */
-            pTstEnv->enmMode = AUDIOTESTMODE_HOST;
-
-            if (!pCtx->Host.uGuestAtsPort)
-                pCtx->Host.uGuestAtsPort = ATS_TCP_ALT_PORT;
-
-            rc = audioTestEnvInit(pTstEnv, &g_DrvHostValidationKitAudio, true /* fWithDrvAudio */,
-                                  pCtx->Host.szGuestAtsAddr, pCtx->Host.uGuestAtsPort);
-            if (RT_SUCCESS(rc))
-            {
-                audioTestWorker(pTstEnv, &TstCust);
-                audioTestEnvDestroy(pTstEnv);
-            }
+            audioTestWorker(pTstEnv, &TstCust);
+            audioTestEnvDestroy(pTstEnv);
         }
     }
@@ -170,13 +182,15 @@
     ASMAtomicWriteBool(&g_fTerminate, true);
 
-    int rcThread;
-    int rc2 = RTThreadWait(hThreadGstAts, RT_MS_30SEC, &rcThread);
-    if (RT_SUCCESS(rc2))
-        rc2 = rcThread;
-    if (RT_FAILURE(rc2))
-        RTTestFailed(g_hTest, "Shutting down self test failed with %Rrc\n", rc2);
-
-    if (RT_SUCCESS(rc))
-        rc = rc2;
+    if (fStartGuestAts)
+    {
+        int rcThread;
+        int rc2 = RTThreadWait(hThreadGstAts, RT_MS_30SEC, &rcThread);
+        if (RT_SUCCESS(rc2))
+            rc2 = rcThread;
+        if (RT_FAILURE(rc2))
+            RTTestFailed(g_hTest, "Shutting down guest ATS failed with %Rrc\n", rc2);
+        if (RT_SUCCESS(rc))
+            rc = rc2;
+    }
 
     if (RT_FAILURE(rc))
Index: trunk/src/VBox/ValidationKit/utils/audio/vkatCommon.cpp
===================================================================
--- trunk/src/VBox/ValidationKit/utils/audio/vkatCommon.cpp	(revision 89545)
+++ trunk/src/VBox/ValidationKit/utils/audio/vkatCommon.cpp	(revision 89575)
@@ -31,4 +31,5 @@
 
 #include <iprt/ctype.h>
+#include <iprt/dir.h>
 #include <iprt/errcore.h>
 #include <iprt/getopt.h>
@@ -401,11 +402,7 @@
     PAUDIOTESTENV   pTstEnv = pCtx->pTstEnv;
 
-    char szTag[AUDIOTEST_TAG_MAX];
-    int rc = RTStrPrintf2(szTag, sizeof(szTag), "%s-guest", pszTag);
-    AssertRCReturn(rc, rc);
-
-    RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Beginning test set '%s'\n", szTag);
-
-    return AudioTestSetCreate(&pTstEnv->Set, pTstEnv->szPathTemp, szTag);
+    RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Beginning test set '%s'\n", pszTag);
+
+    return AudioTestSetCreate(&pTstEnv->Set, pTstEnv->szPathTemp, pszTag);
 }
 
@@ -413,6 +410,4 @@
 static DECLCALLBACK(int) audioTestSvcTestSetEndCallback(void const *pvUser, const char *pszTag)
 {
-    RT_NOREF(pszTag);
-
     PATSCALLBACKCTX pCtx    = (PATSCALLBACKCTX)pvUser;
     PAUDIOTESTENV   pTstEnv = pCtx->pTstEnv;
@@ -518,13 +513,50 @@
  * @param   pDrvReg             Audio driver to use.
  * @param   fWithDrvAudio       Whether to include DrvAudio in the stack or not.
- * @param   pszTcpAddr          TCP/IP address to connect to.
+ * @param   pszHostTcpAddr      Host ATS TCP/IP address to connect to.
+ *                              If NULL, ATS_TCP_HOST_DEFAULT_ADDR_STR will be used.
+ * @param   uHostTcpPort        Host ATS TCP/IP port to connect to.
+ *                              If 0, ATS_TCP_HOST_DEFAULT_PORT will be used.
+ * @param   pszGuestTcpAddr     Guest ATS TCP/IP address to connect to.
  *                              If NULL, localhost (127.0.0.1) will be used.
- * @param   uTcpPort            TCP/IP port to connect to.
- *                              If 0, ATS_DEFAULT_PORT will be used.
+ * @param   uGuestTcpPort       Guest ATS TCP/IP port to connect to.
+ *                              If 0, ATS_TCP_GUEST_DEFAULT_PORT will be used.
  */
 int audioTestEnvInit(PAUDIOTESTENV pTstEnv,
                      PCPDMDRVREG pDrvReg, bool fWithDrvAudio,
-                     const char *pszTcpAddr, uint32_t uTcpPort)
-{
+                     const char *pszHostTcpAddr, uint32_t uHostTcpPort,
+                     const char *pszGuestTcpAddr, uint32_t uGuestTcpPort)
+{
+    int rc = VINF_SUCCESS;
+
+    /*
+     * Set sane defaults if not already set.
+     */
+    if (!RTStrNLen(pTstEnv->szTag, sizeof(pTstEnv->szTag)))
+    {
+        rc = AudioTestGenTag(pTstEnv->szTag, sizeof(pTstEnv->szTag));
+        AssertRCReturn(rc, rc);
+    }
+
+    if (!RTStrNLen(pTstEnv->szPathTemp, sizeof(pTstEnv->szPathTemp)))
+    {
+        rc = AudioTestPathGetTemp(pTstEnv->szPathTemp, sizeof(pTstEnv->szPathTemp));
+        AssertRCReturn(rc, rc);
+    }
+
+    if (!RTStrNLen(pTstEnv->szPathOut, sizeof(pTstEnv->szPathOut)))
+    {
+        rc = RTPathJoin(pTstEnv->szPathOut, sizeof(pTstEnv->szPathOut), pTstEnv->szPathTemp, "vkat-temp");
+        AssertRCReturn(rc, rc);
+    }
+
+    if (pDrvReg == NULL) /* Go with the platform's default backend if nothing else is set. */
+        pDrvReg = g_aBackends[0].pDrvReg;
+
+    if (!uHostTcpPort)
+        uHostTcpPort = ATS_TCP_HOST_DEFAULT_PORT;
+
+    if (!uGuestTcpPort)
+        uGuestTcpPort = ATS_TCP_GUEST_DEFAULT_PORT;
+
     RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test mode is '%s'\n", pTstEnv->enmMode == AUDIOTESTMODE_HOST ? "host" : "guest");
     RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Using tag '%s'\n", pTstEnv->szTag);
@@ -532,6 +564,4 @@
     RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Temp directory is '%s'\n", pTstEnv->szPathTemp);
 
-    int rc = VINF_SUCCESS;
-
     PDMAudioHostEnumInit(&pTstEnv->DevEnum);
 
@@ -544,8 +574,10 @@
                                  /* The self test mode drives the ValKit audio driver locally,
                                   * so also use the driver stack here. */
-                                 || pTstEnv->fSelftest;
+                                 || (   pTstEnv->enmMode == AUDIOTESTMODE_HOST
+                                     && pTstEnv->fSelftest);
     if (fUseDriverStack)
     {
-        rc = audioTestDriverStackInit(&pTstEnv->DrvStack, pDrvReg, fWithDrvAudio);
+        rc = audioTestDriverStackInitEx(&pTstEnv->DrvStack, pDrvReg,
+                                        true /* fEnabledIn */, true /* fEnabledOut */, fWithDrvAudio);
         if (RT_FAILURE(rc))
             return rc;
@@ -586,6 +618,14 @@
         Callbacks.pvUser          = &Ctx;
 
-        RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Starting guest ATS at %s:%RU32...\n", pszTcpAddr, uTcpPort);
-        rc = AudioTestSvcInit(&pTstEnv->u.Guest.Srv, pszTcpAddr, uTcpPort, &Callbacks);
+        /*
+         * Start the ATS (Audio Test Service) on the guest side.
+         * That service then will perform playback and recording operations on the guest, triggered from the host.
+         *
+         * When running this in self-test mode, that service also will be run on the host.
+         */
+        RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Starting guest ATS at %s:%RU32...\n",
+                     (pszGuestTcpAddr && *pszGuestTcpAddr) ? pszGuestTcpAddr : "127.0.0.1",
+                     uGuestTcpPort ? uGuestTcpPort : ATS_TCP_GUEST_DEFAULT_PORT);
+        rc = AudioTestSvcInit(&pTstEnv->u.Guest.Srv, pszGuestTcpAddr, uGuestTcpPort, &Callbacks);
         if (RT_SUCCESS(rc))
             rc = AudioTestSvcStart(&pTstEnv->u.Guest.Srv);
@@ -599,15 +639,29 @@
     else /* Host mode */
     {
-        RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Connecting to guest ATS at %s:%RU32 ...\n",
-                     (pszTcpAddr && *pszTcpAddr) ? pszTcpAddr : "127.0.0.1", uTcpPort ? uTcpPort : ATS_TCP_DEFAULT_PORT);
-
-        rc = AudioTestSvcClientConnect(&pTstEnv->u.Host.AtsClGuest, pszTcpAddr, uTcpPort);
+        RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Connecting to host ATS at %s:%RU32 ...\n",
+                     (pszHostTcpAddr && *pszHostTcpAddr) ? pszHostTcpAddr : ATS_TCP_HOST_DEFAULT_ADDR_STR,
+                     uHostTcpPort ? uHostTcpPort : ATS_TCP_HOST_DEFAULT_PORT);
+
+        rc = AudioTestSvcClientConnect(&pTstEnv->u.Host.AtsClValKit, pszHostTcpAddr, uHostTcpPort);
         if (RT_FAILURE(rc))
         {
-            RTTestFailed(g_hTest, "Connecting to ATS failed with %Rrc\n", rc);
+            RTTestFailed(g_hTest, "Connecting to host ATS failed with %Rrc\n", rc);
             return rc;
         }
 
-        RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Connected to ATS\n");
+        RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Connected to host ATS\n");
+
+        RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Connecting to guest ATS at %s:%RU32 ...\n",
+                     (pszGuestTcpAddr && *pszGuestTcpAddr) ? pszGuestTcpAddr : "127.0.0.1",
+                     uGuestTcpPort ? uGuestTcpPort : ATS_TCP_GUEST_DEFAULT_PORT);
+
+        rc = AudioTestSvcClientConnect(&pTstEnv->u.Host.AtsClGuest, pszGuestTcpAddr, uGuestTcpPort);
+        if (RT_FAILURE(rc))
+        {
+            RTTestFailed(g_hTest, "Connecting to guest ATS failed with %Rrc\n", rc);
+            return rc;
+        }
+
+        RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Connected to guest ATS\n");
     }
 
@@ -637,4 +691,8 @@
             RTTestFailed(g_hTest, "Stream destruction for stream #%u failed with %Rrc\n", i, rc2);
     }
+
+    /* Try cleaning up a bit. */
+    RTDirRemove(pTstEnv->szPathTemp);
+    RTDirRemove(pTstEnv->szPathOut);
 
     audioTestDriverStackDelete(&pTstEnv->DrvStack);
@@ -659,7 +717,5 @@
         RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test set packed up to '%s'\n", szFileOut);
 
-    int rc2 = AudioTestSetWipe(&pTstEnv->Set);
-    if (RT_SUCCESS(rc))
-        rc = rc2;
+    /* ignore rc */ AudioTestSetWipe(&pTstEnv->Set);
 
     AudioTestSetDestroy(&pTstEnv->Set);
Index: trunk/src/VBox/ValidationKit/utils/audio/vkatDriverStack.cpp
===================================================================
--- trunk/src/VBox/ValidationKit/utils/audio/vkatDriverStack.cpp	(revision 89545)
+++ trunk/src/VBox/ValidationKit/utils/audio/vkatDriverStack.cpp	(revision 89575)
@@ -490,12 +490,14 @@
 
 /**
- * Initializes a driver stack.
+ * Initializes a driver stack, extended version.
  *
  * @returns VBox status code.
  * @param   pDrvStack       The driver stack to initialize.
  * @param   pDrvReg         The backend driver to use.
+ * @param   fEnabledIn      Whether input is enabled or not on creation time.
+ * @param   fEnabledOut     Whether output is enabled or not on creation time.
  * @param   fWithDrvAudio   Whether to include DrvAudio in the stack or not.
  */
-int audioTestDriverStackInit(PAUDIOTESTDRVSTACK pDrvStack, PCPDMDRVREG pDrvReg, bool fWithDrvAudio)
+int audioTestDriverStackInitEx(PAUDIOTESTDRVSTACK pDrvStack, PCPDMDRVREG pDrvReg, bool fEnabledIn, bool fEnabledOut, bool fWithDrvAudio)
 {
     int rc;
@@ -516,8 +518,14 @@
             if (pDrvStack->pIAudioConnector)
             {
-                /* Both input and output is disabled by default. Fix that: */
-                rc = pDrvStack->pIAudioConnector->pfnEnable(pDrvStack->pIAudioConnector, PDMAUDIODIR_OUT, true);
+                /* Both input and output is disabled by default. */
+                if (fEnabledIn)
+                    rc = pDrvStack->pIAudioConnector->pfnEnable(pDrvStack->pIAudioConnector, PDMAUDIODIR_IN, true);
+
                 if (RT_SUCCESS(rc))
-                    rc = pDrvStack->pIAudioConnector->pfnEnable(pDrvStack->pIAudioConnector, PDMAUDIODIR_IN, true);
+                {
+                    if (fEnabledOut)
+                        rc = pDrvStack->pIAudioConnector->pfnEnable(pDrvStack->pIAudioConnector, PDMAUDIODIR_OUT, true);
+                }
+
                 if (RT_FAILURE(rc))
                 {
@@ -556,4 +564,20 @@
 
     return rc;
+}
+
+
+/**
+ * Initializes a driver stack.
+ *
+ * @returns VBox status code.
+ * @param   pDrvStack       The driver stack to initialize.
+ * @param   pDrvReg         The backend driver to use.
+ * @param   fEnabledIn      Whether input is enabled or not on creation time.
+ * @param   fEnabledOut     Whether output is enabled or not on creation time.
+ * @param   fWithDrvAudio   Whether to include DrvAudio in the stack or not.
+ */
+int audioTestDriverStackInit(PAUDIOTESTDRVSTACK pDrvStack, PCPDMDRVREG pDrvReg, bool fWithDrvAudio)
+{
+    return audioTestDriverStackInitEx(pDrvStack, pDrvReg, true /* fEnabledIn */, true /* fEnabledOut */, fWithDrvAudio);
 }
 
Index: trunk/src/VBox/ValidationKit/utils/audio/vkatInternal.h
===================================================================
--- trunk/src/VBox/ValidationKit/utils/audio/vkatInternal.h	(revision 89545)
+++ trunk/src/VBox/ValidationKit/utils/audio/vkatInternal.h	(revision 89575)
@@ -281,5 +281,5 @@
             /** Client connected to the ATS on the guest side. */
             ATSCLIENT       AtsClGuest;
-            /** Client connected to the ATS on the Validation Kit. */
+            /** Client connected to the Validation Kit audio driver ATS. */
             ATSCLIENT       AtsClValKit;
         } Host;
@@ -319,4 +319,10 @@
          *  Defaults to the platform's default driver. */
         PCPDMDRVREG  pDrvReg;
+        /** Where to bind the address of the guest ATS instance to.
+         *  Defaults to localhost (127.0.0.1) if empty. */
+        char         szAtsAddr[64];
+        /** Port of the guest ATS instance.
+         *  Defaults to ATS_ALT_PORT if not set. */
+        uint32_t     uAtsPort;
     } Guest;
     struct
@@ -347,4 +353,5 @@
  * @{ */
 void        audioTestDriverStackDelete(PAUDIOTESTDRVSTACK pDrvStack);
+int         audioTestDriverStackInitEx(PAUDIOTESTDRVSTACK pDrvStack, PCPDMDRVREG pDrvReg, bool fEnabledIn, bool fEnabledOut, bool fWithDrvAudio);
 int         audioTestDriverStackInit(PAUDIOTESTDRVSTACK pDrvStack, PCPDMDRVREG pDrvReg, bool fWithDrvAudio);
 int         audioTestDriverStackSetDevice(PAUDIOTESTDRVSTACK pDrvStack, PDMAUDIODIR enmDir, const char *pszDevId);
@@ -405,5 +412,5 @@
 /** @name Test environment handling
  * @{ */
-int         audioTestEnvInit(PAUDIOTESTENV pTstEnv, PCPDMDRVREG pDrvReg, bool fWithDrvAudio, const char *pszTcpAddr, uint32_t uTcpPort);
+int         audioTestEnvInit(PAUDIOTESTENV pTstEnv, PCPDMDRVREG pDrvReg, bool fWithDrvAudio, const char *pszHostTcpAddr, uint32_t uHostTcpPort, const char *pszGuestTcpAddr, uint32_t uGuestTcpPort);
 void        audioTestEnvDestroy(PAUDIOTESTENV pTstEnv);
 int         audioTestEnvPrologue(PAUDIOTESTENV pTstEnv);
