VirtualBox

Changeset 89054 in vbox for trunk/src/VBox/ValidationKit


Ignore:
Timestamp:
May 15, 2021 2:14:57 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
144394
Message:

ValKit/Audio: Command line parsing fixes. Tag inconsistencies and crashes. bugref:10008

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/utils/audio/vkat.cpp

    r89051 r89054  
    3030*********************************************************************************************************************************/
    3131#include <iprt/buildconfig.h>
     32#include <iprt/ctype.h>
    3233#include <iprt/errcore.h>
    3334#include <iprt/initterm.h>
    3435#include <iprt/getopt.h>
     36#include <iprt/message.h>
    3537#include <iprt/path.h>
    36 #include <iprt/message.h>
    3738#include <iprt/process.h>
    3839#include <iprt/rand.h>
     
    5455
    5556/*********************************************************************************************************************************
    56 *   Defined Constants And Macros                                                                                                 *
    57 *********************************************************************************************************************************/
    58 
    59 
    60 /*********************************************************************************************************************************
    61 *   Prototypes                                                                                                                   *
     57*   Structures and Typedefs                                                                                                      *
    6258*********************************************************************************************************************************/
    6359struct AUDIOTESTENV;
     60/** Pointer a audio test environment. */
     61typedef AUDIOTESTENV *PAUDIOTESTENV;
     62
    6463struct AUDIOTESTDESC;
    65 struct AUDIOTESTPARMS;
    66 
    67 
    68 /*********************************************************************************************************************************
    69 *   Structures and Typedefs                                                                                                      *
    70 *********************************************************************************************************************************/
     64/** Pointer a audio test descriptor. */
     65typedef AUDIOTESTDESC *PAUDIOTESTDESC;
    7166
    7267/**
     
    7974 * @param   pTstParmsAcq    The audio test parameters to set up.
    8075 */
    81 typedef DECLCALLBACKTYPE(int, FNAUDIOTESTSETUP,(AUDIOTESTENV *pTstEnv, AUDIOTESTDESC *pTstDesc, PAUDIOTESTPARMS pTstParmsAcq, void **ppvCtx));
     76typedef DECLCALLBACKTYPE(int, FNAUDIOTESTSETUP,(PAUDIOTESTENV pTstEnv, PAUDIOTESTDESC pTstDesc, PAUDIOTESTPARMS pTstParmsAcq, void **ppvCtx));
    8277/** Pointer to an audio test setup callback. */
    8378typedef FNAUDIOTESTSETUP *PFNAUDIOTESTSETUP;
    8479
    85 typedef DECLCALLBACKTYPE(int, FNAUDIOTESTEXEC,(AUDIOTESTENV *pTstEnv, void *pvCtx, PAUDIOTESTPARMS pTstParms));
     80typedef DECLCALLBACKTYPE(int, FNAUDIOTESTEXEC,(PAUDIOTESTENV pTstEnv, void *pvCtx, PAUDIOTESTPARMS pTstParms));
    8681/** Pointer to an audio test exec callback. */
    8782typedef FNAUDIOTESTEXEC *PFNAUDIOTESTEXEC;
    8883
    89 typedef DECLCALLBACKTYPE(int, FNAUDIOTESTDESTROY,(AUDIOTESTENV *pTstEnv, void *pvCtx));
     84typedef DECLCALLBACKTYPE(int, FNAUDIOTESTDESTROY,(PAUDIOTESTENV pTstEnv, void *pvCtx));
    9085/** Pointer to an audio test destroy callback. */
    9186typedef FNAUDIOTESTDESTROY *PFNAUDIOTESTDESTROY;
     
    107102    PPDMIHOSTAUDIO        pDrvAudio;
    108103    /** The current (last) audio device enumeration to use. */
    109     PDMAUDIOHOSTENUM      DevEnm;
     104    PDMAUDIOHOSTENUM      DevEnum;
     105    /** Audio stream. */
    110106    AUDIOTESTSTREAM       aStreams[AUDIOTESTENV_MAX_STREAMS];
    111107    /** The audio test set to use. */
    112108    AUDIOTESTSET          Set;
    113109} AUDIOTESTENV;
    114 /** Pointer a audio test environment. */
    115 typedef AUDIOTESTENV *PAUDIOTESTENV;
    116110
    117111/**
     
    131125    PFNAUDIOTESTDESTROY     pfnDestroy;
    132126} AUDIOTESTDESC;
    133 /** Pointer a audio test descriptor. */
    134 typedef AUDIOTESTDESC *PAUDIOTESTDESC;
    135127
    136128
    137129/*********************************************************************************************************************************
    138 *   Forward declarations                                                                                                         *
     130*   Internal Functions                                                                                                           *
    139131*********************************************************************************************************************************/
    140132static int audioTestCombineParms(PAUDIOTESTPARMS pBaseParms, PAUDIOTESTPARMS pOverrideParms);
    141133static int audioTestPlayTone(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PAUDIOTESTTONEPARMS pParms);
    142134static int audioTestStreamDestroy(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream);
     135static DECLCALLBACK(RTEXITCODE) audioTestMain(int argc, char **argv);
     136static DECLCALLBACK(RTEXITCODE) audioVerifyMain(int argc, char **argv);
    143137
    144138
     
    177171static const RTGETOPTDEF g_aCmdCommonOptions[] =
    178172{
    179     { "--help",             'h',                          RTGETOPT_REQ_NOTHING },
    180     { "--verbose",          'v',                          RTGETOPT_REQ_NOTHING }
     173    { "--quiet",            'q',                          RTGETOPT_REQ_NOTHING },
     174    { "--verbose",          'v',                          RTGETOPT_REQ_NOTHING },
    181175};
    182176
     
    211205};
    212206
     207/**
     208 * Commands.
     209 */
     210static struct
     211{
     212    const char     *pszCommand;
     213    DECLCALLBACKMEMBER(RTEXITCODE, pfnHandler,(int argc, char **argv));
     214    PCRTGETOPTDEF   paOptions;
     215    size_t          cOptions;
     216    const char     *pszDesc;
     217} const g_aCommands[] =
     218{
     219    {
     220        "test",   audioTestMain,      g_aCmdTestOptions,      RT_ELEMENTS(g_aCmdTestOptions),
     221        "Does some kind of testing, I guess..."
     222    },
     223    {
     224        "verify", audioVerifyMain,    g_aCmdVerifyOptions,    RT_ELEMENTS(g_aCmdVerifyOptions),
     225        "Verfies something, I guess..."
     226    },
     227};
     228
    213229/** The test handle. */
    214 static RTTEST g_hTest;
     230static RTTEST       g_hTest;
     231/** The current verbosity level. */
     232static unsigned     g_uVerbosity = 0;
    215233/** The driver instance data. */
    216 PDMDRVINS g_DrvIns;
    217 /** The current verbosity level. */
    218 unsigned  g_uVerbosity = 0;
     234static PDMDRVINS    g_DrvIns;
    219235
    220236
     
    235251{
    236252    pTstEnv->pDrvAudio = pDrvAudio;
    237     PDMAudioHostEnumInit(&pTstEnv->DevEnm);
     253    PDMAudioHostEnumInit(&pTstEnv->DevEnum);
    238254
    239255    int rc = VINF_SUCCESS;
     
    275291        return;
    276292
    277     PDMAudioHostEnumDelete(&pTstEnv->DevEnm);
     293    PDMAudioHostEnumDelete(&pTstEnv->DevEnum);
    278294
    279295    for (unsigned i = 0; i < RT_ELEMENTS(pTstEnv->aStreams); i++)
     
    294310static void audioTestParmsInit(PAUDIOTESTPARMS pTstParms)
    295311{
    296     RT_BZERO(pTstParms, sizeof(AUDIOTESTPARMS));
    297 
    298     return;
     312    RT_ZERO(*pTstParms);
    299313}
    300314
     
    313327
    314328/**
    315  * Shows the application logo.
     329 * Shows the logo.
    316330 *
    317331 * @param   pStream             Output stream to show logo on.
    318332 */
    319 void showLogo(PRTSTREAM pStream)
    320 {
    321     static bool s_fLogoShown = false; /* Show logo only once. */
    322 
    323     if (!s_fLogoShown)
    324     {
    325         RTStrmPrintf(pStream, VBOX_PRODUCT " VKAT (Validation Kit Audio Test) "
    326                      VBOX_VERSION_STRING " - r%s\n"
    327                      "(C) " VBOX_C_YEAR " " VBOX_VENDOR "\n"
    328                      "All rights reserved.\n\n", RTBldCfgRevisionStr());
    329         s_fLogoShown = true;
    330     }
     333static void audioTestShowLogo(PRTSTREAM pStream)
     334{
     335    RTStrmPrintf(pStream, VBOX_PRODUCT " VKAT (Validation Kit Audio Test) "
     336                 VBOX_VERSION_STRING " - r%s\n"
     337                 "(C) " VBOX_C_YEAR " " VBOX_VENDOR "\n"
     338                 "All rights reserved.\n\n", RTBldCfgRevisionStr());
    331339}
    332340
     
    336344static void audioTestUsage(PRTSTREAM pStrm)
    337345{
    338     char szExec[RTPATH_MAX];
    339     RTStrmPrintf(pStrm, "usage: %s [options]\n",
    340                  RTPathFilename(RTProcGetExecutablePath(szExec, sizeof(szExec))));
    341     RTStrmPrintf(pStrm, "\n");
    342     RTStrmPrintf(pStrm, "options: \n");
    343 
    344     for (unsigned i = 0; i < RT_ELEMENTS(g_aCmdTestOptions); i++)
    345     {
    346         const char *pszHelp;
    347         switch (g_aCmdTestOptions[i].iShort)
     346    RTStrmPrintf(pStrm, "usage: %s [global options] <command> [command-options]\n",
     347                 RTPathFilename(RTProcExecutablePath()));
     348    RTStrmPrintf(pStrm,
     349                 "\n"
     350                 "Global Options:\n"
     351                 "  -q, --quiet\n"
     352                 "    Sets verbosity to zero.\n"
     353                 "  -v, --verbose\n"
     354                 "    Increase verbosity.\n"
     355                 "  -V, --version\n"
     356                 "    Displays version.\n"
     357                 "  -h, -?, --help\n"
     358                 "    Displays help.\n"
     359                 );
     360
     361    for (uintptr_t iCmd = 0; iCmd < RT_ELEMENTS(g_aCommands); iCmd++)
     362    {
     363        RTStrmPrintf(pStrm,
     364                     "\n"
     365                     "Command '%s':\n"
     366                     "    %s\n"
     367                     "Options for '%s':\n",
     368                     g_aCommands[iCmd].pszCommand, g_aCommands[iCmd].pszDesc, g_aCommands[iCmd].pszCommand);
     369        PCRTGETOPTDEF const paOptions = g_aCommands[iCmd].paOptions;
     370        for (unsigned i = 0; i < g_aCommands[iCmd].cOptions; i++)
    348371        {
    349             case 'h':
    350                 pszHelp = "Displays this help and exit";
    351                 break;
    352             case 'd':
    353                 pszHelp = "Use the specified audio device";
    354                 break;
    355             case 'e':
    356                 pszHelp = "Exclude the given test id from the list";
    357                 break;
    358             case 'a':
    359                 pszHelp = "Exclude all tests from the list (useful to enable single tests later with --include)";
    360                 break;
    361             case 'i':
    362                 pszHelp = "Include the given test id in the list";
    363                 break;
    364             default:
    365                 pszHelp = "Option undocumented";
    366                 break;
     372            if (RT_C_IS_PRINT(paOptions[i].iShort))
     373                RTStrmPrintf(pStrm, "  -%c, %s\n", g_aCmdTestOptions[i].iShort, g_aCmdTestOptions[i].pszLong);
     374            else
     375                RTStrmPrintf(pStrm, "  %s\n", g_aCmdTestOptions[i].pszLong);
     376
     377            const char *pszHelp = NULL;
     378            if (paOptions == g_aCmdTestOptions)
     379            {
     380                switch (g_aCmdTestOptions[i].iShort)
     381                {
     382                    case 'd':
     383                        pszHelp = "Use the specified audio device";
     384                        break;
     385                    case 'e':
     386                        pszHelp = "Exclude the given test id from the list";
     387                        break;
     388                    case 'a':
     389                        pszHelp = "Exclude all tests from the list (useful to enable single tests later with --include)";
     390                        break;
     391                    case 'i':
     392                        pszHelp = "Include the given test id in the list";
     393                        break;
     394                }
     395            }
     396            /** @todo Add help text for all options. */
     397            if (pszHelp)
     398                RTStrmPrintf(pStrm, "    %s\n", pszHelp);
    367399        }
    368         char szOpt[256];
    369         RTStrPrintf(szOpt, sizeof(szOpt), "%s, -%c", g_aCmdTestOptions[i].pszLong, g_aCmdTestOptions[i].iShort);
    370         RTStrmPrintf(pStrm, "  %-30s%s\n", szOpt, pszHelp);
    371     }
    372 
    373     /** @todo Add all other options. */
     400    }
     401
    374402}
    375403
     
    452480        *ppDev = NULL;
    453481
    454     int rc = pTstEnv->pDrvAudio->pfnGetDevices(pTstEnv->pDrvAudio, &pTstEnv->DevEnm);
     482    int rc = pTstEnv->pDrvAudio->pfnGetDevices(pTstEnv->pDrvAudio, &pTstEnv->DevEnum);
    455483    if (RT_SUCCESS(rc))
    456484    {
    457485        PPDMAUDIOHOSTDEV pDev;
    458         RTListForEach(&pTstEnv->DevEnm.LstDevices, pDev, PDMAUDIOHOSTDEV, ListEntry)
     486        RTListForEach(&pTstEnv->DevEnum.LstDevices, pDev, PDMAUDIOHOSTDEV, ListEntry)
    459487        {
    460488            char szFlags[PDMAUDIOHOSTDEV_MAX_FLAGS_STRING_LEN];
     
    856884 * @param   argv                argv arguments.
    857885 */
    858 int audioTestMain(int argc, char **argv)
     886static DECLCALLBACK(RTEXITCODE) audioTestMain(int argc, char **argv)
    859887{
    860888    AUDIOTESTENV TstEnv;
     
    864892    audioTestParmsInit(&TstCust);
    865893
    866     char *pszDevice  = NULL; /* Custom device to use. Can be NULL if not being used. */
    867     char *pszTag     = NULL; /* Custom tag to use. Can be NULL if not being used. */
    868 
    869     RT_ZERO(g_DrvIns);
    870     const PDMDRVREG *pDrvReg = NULL;
     894    const char *pszDevice  = NULL; /* Custom device to use. Can be NULL if not being used. */
     895    const char *pszTag     = NULL; /* Custom tag to use. Can be NULL if not being used. */
     896
     897    /* The backend: */
     898    PDMDRVREG const *pDrvReg;
     899#if defined(RT_OS_WINDOWS)
     900    pDrvReg = &g_DrvHostAudioWas;
     901#elif defined(RT_OS_DARWIN)
     902    pDrvReg = &g_DrvHostCoreAudio;
     903#elif defined(RT_OS_SOLARIS)
     904    pDrvReg = &g_DrvHostOSSAudio;
     905#elif defined(RT_OS_LINUX) && defined(VBOX_WITH_AUDIO_ALSA)
     906    pDrvReg = &g_DrvHostALSAAudio;
     907#elif defined(RT_OS_LINUX) && defined(VBOX_WITH_AUDIO_PULSE)
     908    pDrvReg = &g_DrvHostPulseAudio;
     909#elif defined(RT_OS_LINUX) && defined(VBOX_WITH_AUDIO_OSS)
     910    pDrvReg = &g_DrvHostPulseAudio;
     911#else
     912# error "Port me!"
     913#endif
    871914
    872915    RTGETOPTUNION ValueUnion;
    873916    RTGETOPTSTATE GetState;
    874     int rc = RTGetOptInit(&GetState, argc, argv, g_aCmdTestOptions, RT_ELEMENTS(g_aCmdTestOptions), 0, 0 /* fFlags */);
     917    int rc = RTGetOptInit(&GetState, argc, argv, g_aCmdTestOptions, RT_ELEMENTS(g_aCmdTestOptions), 1, 0 /*fFlags*/);
    875918    AssertRCReturn(rc, RTEXITCODE_INIT);
    876919
     
    880923        {
    881924            case 'h':
    882             {
    883925                audioTestUsage(g_pStdOut);
    884926                return RTEXITCODE_SUCCESS;
    885             }
    886 
    887             case 'e':
    888             {
    889                 if (ValueUnion.u32 < RT_ELEMENTS(g_aTests))
    890                     g_aTests[ValueUnion.u32].fExcluded = true;
    891                 else
    892                 {
    893                     RTTestPrintf(g_hTest, RTTESTLVL_FAILURE, "Invalid test number passed to --exclude\n");
    894                     RTTestErrorInc(g_hTest);
    895                     return RTGetOptPrintError(VERR_INVALID_PARAMETER, &ValueUnion);
    896                 }
    897                 break;
    898             }
    899927
    900928            case 'a':
    901             {
    902929                for (unsigned i = 0; i < RT_ELEMENTS(g_aTests); i++)
    903930                    g_aTests[i].fExcluded = true;
    904931                break;
    905             }
    906932
    907933            case 'b':
    908             {
     934                pDrvReg = NULL;
    909935#ifdef VBOX_WITH_AUDIO_PULSE
    910                 if (   !RTStrICmp(ValueUnion.psz, "pulseaudio")
    911                     || !RTStrICmp(ValueUnion.psz, "pa"))
     936                if (   !strcmp(ValueUnion.psz, "pulseaudio")
     937                    || !strcmp(ValueUnion.psz, "pa"))
    912938                    pDrvReg = &g_DrvHostPulseAudio;
    913939#endif
    914940#ifdef VBOX_WITH_AUDIO_ALSA
    915                 if (   !RTStrICmp(ValueUnion.psz, "alsa"))
     941                if (   !strcmp(ValueUnion.psz, "alsa"))
    916942                    pDrvReg = &g_DrvHostALSAAudio;
    917943#endif
    918944#ifdef VBOX_WITH_AUDIO_OSS
    919                 if (   !RTStrICmp(ValueUnion.psz, "oss"))
     945                if (   !strcmp(ValueUnion.psz, "oss"))
    920946                    pDrvReg = &g_DrvHostOSSAudio;
    921947#endif
    922948#if defined(RT_OS_DARWIN)
    923                 if (   !RTStrICmp(ValueUnion.psz, "coreaudio"))
     949                if (   !strcmp(ValueUnion.psz, "coreaudio"))
    924950                    pDrvReg = &g_DrvHostCoreAudio;
    925951#endif
    926952#if defined(RT_OS_WINDOWS)
    927                 if (        !RTStrICmp(ValueUnion.psz, "wasapi"))
     953                if (        !strcmp(ValueUnion.psz, "wasapi"))
    928954                    pDrvReg = &g_DrvHostAudioWas;
    929                 else if (   !RTStrICmp(ValueUnion.psz, "directsound")
    930                          || !RTStrICmp(ValueUnion.psz, "dsound")
     955                else if (   !strcmp(ValueUnion.psz, "directsound")
     956                         || !strcmp(ValueUnion.psz, "dsound")
    931957                    pDrvReg = &g_DrvHostDSound;
    932958#endif
    933959                if (pDrvReg == NULL)
    934                     return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Invalid / unsupported backend '%s' specified\n", ValueUnion.psz);
    935                 break;
    936             }
     960                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Unknown backend: '%s'", ValueUnion.psz);
     961                break;
     962
     963            case 'e':
     964                if (ValueUnion.u32 >= RT_ELEMENTS(g_aTests))
     965                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Invalid test number %u passed to --exclude", ValueUnion.u32);
     966                g_aTests[ValueUnion.u32].fExcluded = true;
     967                break;
    937968
    938969            case 'i':
    939             {
    940                 if (ValueUnion.u32 < RT_ELEMENTS(g_aTests))
    941                     g_aTests[ValueUnion.u32].fExcluded = false;
    942                 else
    943                 {
    944                     RTTestPrintf(g_hTest, RTTESTLVL_FAILURE, "Invalid test number passed to --include\n");
    945                     RTTestErrorInc(g_hTest);
    946                     return RTGetOptPrintError(VERR_INVALID_PARAMETER, &ValueUnion);
    947                 }
    948                 break;
    949             }
     970                if (ValueUnion.u32 >= RT_ELEMENTS(g_aTests))
     971                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Invalid test number %u passed to --include", ValueUnion.u32);
     972                g_aTests[ValueUnion.u32].fExcluded = false;
     973                break;
    950974
    951975            case VKAT_TEST_OPT_COUNT:
    952             {
    953                 break;
    954             }
     976                break;
    955977
    956978            case VKAT_TEST_OPT_DEV:
    957             {
    958                 pszDevice = RTStrDup(ValueUnion.psz);
    959                 break;
    960             }
     979                pszDevice = ValueUnion.psz;
     980                break;
    961981
    962982            case VKAT_TEST_OPT_PAUSE:
    963             {
    964                 break;
    965             }
     983                break;
    966984
    967985            case VKAT_TEST_OPT_OUTDIR:
    968             {
    969986                rc = RTStrCopy(TstEnv.szPathOut, sizeof(TstEnv.szPathOut), ValueUnion.psz);
    970987                if (RT_FAILURE(rc))
    971                     return RTMsgErrorExit(RTEXITCODE_FAILURE, "Out dir invalid, rc=%Rrc\n", rc);
    972                 break;
    973             }
     988                    return RTMsgErrorExitFailure("Failed to copy out directory: %Rrc", rc);
     989                break;
    974990
    975991            case VKAT_TEST_OPT_PCM_BIT:
    976             {
     992                /** @todo r=bird: the X suffix means: "fingers off!"   */
    977993                TstCust.TestTone.Props.cbSampleX = ValueUnion.u8 / 8 /* bit */;
    978994                break;
    979             }
    980995
    981996            case VKAT_TEST_OPT_PCM_CHAN:
    982             {
     997                /** @todo r=bird: the X suffix means: "fingers off!"   */
    983998                TstCust.TestTone.Props.cChannelsX = ValueUnion.u8;
    984999                break;
    985             }
    9861000
    9871001            case VKAT_TEST_OPT_PCM_HZ:
    988             {
    9891002                TstCust.TestTone.Props.uHz = ValueUnion.u32;
    9901003                break;
    991             }
    9921004
    9931005            case VKAT_TEST_OPT_PCM_SIGNED:
    994             {
    9951006                TstCust.TestTone.Props.fSigned = ValueUnion.f;
    9961007                break;
    997             }
    9981008
    9991009            case VKAT_TEST_OPT_TAG:
    1000             {
    1001                 pszTag = RTStrDup(ValueUnion.psz);
    1002                 break;
    1003             }
     1010                pszTag = ValueUnion.psz;
     1011                break;
    10041012
    10051013            case VKAT_TEST_OPT_TEMPDIR:
    1006             {
    10071014                rc = RTStrCopy(TstEnv.szPathTemp, sizeof(TstEnv.szPathTemp), ValueUnion.psz);
    10081015                if (RT_FAILURE(rc))
    1009                     return RTMsgErrorExit(RTEXITCODE_FAILURE, "Temp dir invalid, rc=%Rrc\n", rc);
    1010                 break;
    1011             }
     1016                    return RTMsgErrorExit(RTEXITCODE_FAILURE, "Temp dir invalid, rc=%Rrc", rc);
     1017                break;
    10121018
    10131019            case VKAT_TEST_OPT_VOL:
    1014             {
    10151020                TstCust.TestTone.uVolumePercent = ValueUnion.u8;
    10161021                break;
    1017             }
    10181022
    10191023            default:
    1020                 break;
     1024                return RTGetOptPrintError(rc, &ValueUnion);
    10211025        }
    10221026    }
     
    10271031    RTTestBanner(g_hTest);
    10281032
    1029     /* If no backend is specified, go with the default backend for that OS. */
    1030     if (pDrvReg == NULL)
    1031 #if defined(RT_OS_WINDOWS)
    1032         pDrvReg = &g_DrvHostAudioWas;
    1033 #elif defined(RT_OS_DARWIN)
    1034         pDrvReg = &g_DrvHostCoreAudio;
    1035 #elif defined(RT_OS_SOLARIS)
    1036         pDrvReg = &g_DrvHostOSSAudio;
    1037 #else
    1038         pDrvReg = &g_DrvHostALSAAudio;
    1039 #endif
    1040 
    10411033    PPDMIHOSTAUDIO pDrvAudio;
     1034    RT_ZERO(g_DrvIns);
    10421035    rc = audioTestDrvConstruct(pDrvReg, &g_DrvIns, &pDrvAudio);
    10431036    if (RT_SUCCESS(rc))
     
    10691062    audioTestParmsDestroy(&TstCust);
    10701063
    1071     RTStrFree(pszDevice);
    1072     RTStrFree(pszTag);
    1073 
    10741064    if (RT_FAILURE(rc)) /* Let us know that something went wrong in case we forgot to mention it. */
    10751065        RTTestFailed(g_hTest, "Tested failed with %Rrc\n", rc);
     
    10881078 * @param   pszTag              Tag of test set to verify. Optional and can be NULL.
    10891079 */
    1090 int audioVerifyOne(const char *pszPath, const char *pszTag)
     1080static int audioVerifyOne(const char *pszPath, const char *pszTag)
    10911081{
    10921082    RTTestSubF(g_hTest, "Verifying test set (tag '%s') ...", pszTag ? pszTag : "default");
     
    11051095                PAUDIOTESTERRORENTRY pErrEntry;
    11061096                RTListForEach(&errDesc.List, pErrEntry, AUDIOTESTERRORENTRY, Node)
     1097                {
    11071098                    RTTestFailed(g_hTest, pErrEntry->szDesc);
     1099                }
    11081100            }
    11091101            else
     
    11321124 * @param   argv                argv arguments.
    11331125 */
    1134 int audioVerifyMain(int argc, char **argv)
    1135 {
    1136     char *pszTag = NULL; /* Custom tag to use. Can be NULL if not being used. */
    1137 
    1138     char szDirCur[RTPATH_MAX];
    1139     int rc = RTPathGetCurrent(szDirCur, sizeof(szDirCur));
    1140     if (RT_FAILURE(rc))
    1141     {
    1142         RTMsgError("Getting current directory failed, rc=%Rrc\n", rc);
    1143         return RTEXITCODE_FAILURE;
    1144     }
     1126static DECLCALLBACK(RTEXITCODE) audioVerifyMain(int argc, char **argv)
     1127{
     1128    /*
     1129     * Parse options and process arguments.
     1130     */
     1131    RTGETOPTSTATE GetState;
     1132    int rc = RTGetOptInit(&GetState, argc, argv, g_aCmdVerifyOptions, RT_ELEMENTS(g_aCmdVerifyOptions),
     1133                          1, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     1134    AssertRCReturn(rc, RTEXITCODE_INIT);
     1135
     1136    const char   *pszTag   = NULL; /* Custom tag to use. Can be NULL if not being used. */
     1137    unsigned      iTestSet = 0;
     1138    RTGETOPTUNION ValueUnion;
     1139    while ((rc = RTGetOpt(&GetState, &ValueUnion)))
     1140    {
     1141        switch (rc)
     1142        {
     1143            case VKAT_VERIFY_OPT_TAG:
     1144                pszTag = ValueUnion.psz;
     1145                if (g_uVerbosity > 0)
     1146                    RTMsgInfo("Using tag '%s'\n", pszTag);
     1147                break;
     1148
     1149            case VINF_GETOPT_NOT_OPTION:
     1150                if (iTestSet == 0)
     1151                    RTTestBanner(g_hTest);
     1152                audioVerifyOne(ValueUnion.psz, pszTag);
     1153                iTestSet++;
     1154                break;
     1155
     1156            default:
     1157                return RTGetOptPrintError(rc, &ValueUnion);
     1158        }
     1159    }
     1160
     1161    /*
     1162     * If no paths given, default to the current directory.
     1163     */
     1164    if (iTestSet == 0)
     1165    {
     1166        if (iTestSet == 0)
     1167            RTTestBanner(g_hTest);
     1168        char szDirCur[RTPATH_MAX];
     1169        rc = RTPathGetCurrent(szDirCur, sizeof(szDirCur));
     1170        audioVerifyOne(RT_SUCCESS(rc) ? szDirCur : ".", pszTag);
     1171    }
     1172
     1173    /*
     1174     * Print summary and exit.
     1175     */
     1176    return RTTestSummaryAndDestroy(g_hTest);
     1177}
     1178
     1179int main(int argc, char **argv)
     1180{
     1181    /*
     1182     * Init IPRT and globals.
     1183     */
     1184    RTEXITCODE rcExit = RTTestInitAndCreate("AudioTest", &g_hTest);
     1185    if (rcExit != RTEXITCODE_SUCCESS)
     1186        return rcExit;
    11451187
    11461188    /*
     
    11491191    RTGETOPTUNION ValueUnion;
    11501192    RTGETOPTSTATE GetState;
    1151     rc = RTGetOptInit(&GetState, argc, argv, g_aCmdVerifyOptions, RT_ELEMENTS(g_aCmdVerifyOptions),
    1152                       0, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     1193    int rc = RTGetOptInit(&GetState, argc, argv, g_aCmdCommonOptions,
     1194                          RT_ELEMENTS(g_aCmdCommonOptions), 1 /*idxFirst*/, 0 /*fFlags - must not sort! */);
    11531195    AssertRCReturn(rc, RTEXITCODE_INIT);
    11541196
    1155     while ((rc = RTGetOpt(&GetState, &ValueUnion)))
     1197    while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0)
    11561198    {
    11571199        switch (rc)
    11581200        {
    1159             case VKAT_VERIFY_OPT_TAG:
    1160             {
    1161                 pszTag = RTStrDup(ValueUnion.psz);
    1162                 break;
    1163             }
     1201            case 'q':
     1202                g_uVerbosity = 0;
     1203                break;
     1204
     1205            case 'v':
     1206                g_uVerbosity++;
     1207                break;
     1208
     1209            case 'V':
     1210                RTPrintf("v0.0.1\n");
     1211                return RTEXITCODE_SUCCESS;
     1212
     1213            case 'h':
     1214                audioTestShowLogo(g_pStdOut);
     1215                audioTestUsage(g_pStdOut);
     1216                return RTEXITCODE_SUCCESS;
    11641217
    11651218            case VINF_GETOPT_NOT_OPTION:
    11661219            {
    1167                 Assert(GetState.iNext);
    1168                 GetState.iNext--;
    1169                 break;
     1220                for (uintptr_t i = 0; i < RT_ELEMENTS(g_aCommands); i++)
     1221                    if (strcmp(ValueUnion.psz, g_aCommands[i].pszCommand) == 0)
     1222                    {
     1223                        audioTestShowLogo(g_pStdOut);
     1224                        int32_t iCurArg = GetState.iNext - 1;
     1225                        return g_aCommands[i].pfnHandler(argc - iCurArg, argv + iCurArg);
     1226                    }
     1227                RTMsgError("Unknown command '%s'!\n", ValueUnion.psz);
     1228                audioTestUsage(g_pStdErr);
     1229                return RTEXITCODE_SYNTAX;
    11701230            }
    11711231
     
    11731233                return RTGetOptPrintError(rc, &ValueUnion);
    11741234        }
    1175 
    1176         /* All flags / options processed? Bail out here.
    1177          * Processing the file / directory list comes down below. */
    1178         if (rc == VINF_GETOPT_NOT_OPTION)
    1179             break;
    1180     }
    1181 
    1182     if (pszTag)
    1183         RTMsgInfo("Using tag '%s'\n", pszTag);
    1184 
    1185     /*
    1186      * Start testing.
    1187      */
    1188     RTTestBanner(g_hTest);
    1189 
    1190     /*
    1191      * Deal with test sets.
    1192      */
    1193     rc = RTGetOpt(&GetState, &ValueUnion);
    1194     do
    1195     {
    1196         char const *pszPath;
    1197 
    1198         if (rc == 0) /* Use current directory if no element specified. */
    1199             pszPath = szDirCur;
    1200         else
    1201             pszPath = ValueUnion.psz;
    1202 
    1203         RTFSOBJINFO objInfo;
    1204         rc = RTPathQueryInfoEx(pszPath, &objInfo,
    1205                                RTFSOBJATTRADD_UNIX, RTPATH_F_FOLLOW_LINK);
    1206         if (RT_SUCCESS(rc))
    1207         {
    1208             rc = audioVerifyOne(pszPath, pszTag);
    1209         }
    1210         else
    1211             RTTestFailed(g_hTest, "Cannot access path '%s', rc=%Rrc\n", pszPath, rc);
    1212 
    1213     } while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0);
    1214 
    1215     RTStrFree(pszTag);
    1216 
    1217     /*
    1218      * Print summary and exit.
    1219      */
    1220     return RTTestSummaryAndDestroy(g_hTest);
    1221 }
    1222 
    1223 int main(int argc, char **argv)
    1224 {
    1225     /*
    1226      * Init IPRT and globals.
    1227      */
    1228     int rc = RTTestInitAndCreate("AudioTest", &g_hTest);
    1229     if (rc)
    1230         return rc;
    1231 
    1232     AssertReturn(argc > 0, false);
    1233 
    1234     /* At least the operation mode must be there. */
    1235     if (argc < 2)
    1236     {
    1237         audioTestUsage(g_pStdOut);
    1238         return RTEXITCODE_SYNTAX;
    1239     }
    1240 
    1241     /*
    1242      * Process common options.
    1243      */
    1244     RTGETOPTUNION ValueUnion;
    1245     RTGETOPTSTATE GetState;
    1246     rc = RTGetOptInit(&GetState, argc, argv, g_aCmdCommonOptions, RT_ELEMENTS(g_aCmdCommonOptions), 1 /* idxFirst */, 0 /* fFlags */);
    1247     AssertRCReturn(rc, RTEXITCODE_INIT);
    1248 
    1249     while ((rc = RTGetOpt(&GetState, &ValueUnion)))
    1250     {
    1251         switch (rc)
    1252         {
    1253             case 'h':
    1254             {
    1255                 showLogo(g_pStdOut);
    1256                 audioTestUsage(g_pStdOut);
    1257                 return RTEXITCODE_SUCCESS;
    1258             }
    1259 
    1260             case 'v':
    1261             {
    1262                 g_uVerbosity++;
    1263                 break;
    1264             }
    1265 
    1266             case VINF_GETOPT_NOT_OPTION:
    1267             {
    1268                 Assert(GetState.iNext);
    1269                 GetState.iNext--;
    1270             }
    1271 
    1272             default:
    1273                 /* Ignore everything else here. */
    1274                 break;
    1275         }
    1276 
    1277         /* All flags / options processed? Bail out here.
    1278          * Processing the file / directory list comes down below. */
    1279         if (rc == VINF_GETOPT_NOT_OPTION)
    1280             break;
    1281     }
    1282 
    1283     showLogo(g_pStdOut);
    1284 
    1285     /* Get operation mode. */
    1286     const char *pszMode = argv[GetState.iNext++]; /** @todo Also do it busybox-like? */
    1287 
    1288     argv += GetState.iNext;
    1289     Assert(argc >= GetState.iNext);
    1290     argc -= GetState.iNext;
    1291 
    1292     if (!RTStrICmp(pszMode, "test"))
    1293     {
    1294         return audioTestMain(argc, argv);
    1295     }
    1296     else if (!RTStrICmp(pszMode, "verify"))
    1297     {
    1298         return audioVerifyMain(argc, argv);
    1299     }
    1300 
    1301     RTStrmPrintf(g_pStdOut, "Must specify a mode first, either 'test' or 'verify'\n\n");
    1302 
    1303     audioTestUsage(g_pStdOut);
     1235    }
     1236
     1237    RTMsgError("No command specified!\n");
     1238    audioTestUsage(g_pStdErr);
    13041239    return RTEXITCODE_SYNTAX;
    13051240}
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette