VirtualBox

Changeset 70981 in vbox for trunk


Ignore:
Timestamp:
Feb 13, 2018 9:02:21 AM (7 years ago)
Author:
vboxsync
Message:

ValidationKit/SerialTest: Implement status line monitoring testing

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/utils/serial/SerialTest.cpp

    r70761 r70981  
    3535#include <iprt/param.h>
    3636#include <iprt/process.h>
     37#include <iprt/rand.h>
    3738#include <iprt/serialport.h>
    3839#include <iprt/stream.h>
     
    4546*********************************************************************************************************************************/
    4647
    47 
     48/** Number of times to toggle the status lines during the test. */
     49#define SERIALTEST_STS_LINE_TOGGLE_COUNT 100
    4850
    4951/*********************************************************************************************************************************
    5052*   Structures and Typedefs                                                                                                      *
    5153*********************************************************************************************************************************/
     54
     55
     56/**
     57 * Serial test mode.
     58 */
     59typedef enum SERIALTESTMODE
     60{
     61    /** Invalid mode. */
     62    SERIALTESTMODE_INVALID = 0,
     63    /** Serial port is looped back to itself */
     64    SERIALTESTMODE_LOOPBACK,
     65    /** A secondary serial port is used with a null modem cable in between. */
     66    SERIALTESTMODE_SECONDARY,
     67    /** The serial port is connected externally over which we have no control. */
     68    SERIALTESTMODE_EXTERNAL,
     69    /** Usual 32bit hack. */
     70    SERIALTESTMODE_32BIT_HACK = 0x7fffffff
     71} SERIALTESTMODE;
     72/** Pointer to a serial test mode. */
     73typedef SERIALTESTMODE *PSERIALTESTMDOE;
    5274
    5375/** Pointer to the serial test data instance. */
     
    130152    {"--databits",         'c', RTGETOPT_REQ_UINT32 },
    131153    {"--stopbits",         's', RTGETOPT_REQ_STRING },
    132     {"--loopbackdevice",   'l', RTGETOPT_REQ_STRING },
     154    {"--mode",             'm', RTGETOPT_REQ_STRING },
     155    {"--secondarydevice",  'l', RTGETOPT_REQ_STRING },
    133156    {"--tests",            't', RTGETOPT_REQ_STRING },
    134157    {"--txbytes",          'x', RTGETOPT_REQ_UINT32 },
     
    139162static DECLCALLBACK(int) serialTestRunReadWrite(PSERIALTEST pSerialTest);
    140163static DECLCALLBACK(int) serialTestRunWrite(PSERIALTEST pSerialTest);
     164static DECLCALLBACK(int) serialTestRunStsLines(PSERIALTEST pSerialTest);
    141165
    142166/** Implemented tests. */
     
    144168{
    145169    {"readwrite", "Simple Read/Write test on the same serial port",       serialTestRunReadWrite },
    146     {"write",     "Simple write test (verification done somewhere else)", serialTestRunWrite },
     170    {"write",     "Simple write test (verification done somewhere else)", serialTestRunWrite     },
     171    {"stslines",  "Testing the status line setting and receiving",        serialTestRunStsLines  }
    147172};
    148173
    149174/** The test handle. */
    150 static RTTEST          g_hTest               = NIL_RTTEST;
     175static RTTEST          g_hTest                = NIL_RTTEST;
     176/** The serial test mode. */
     177static SERIALTESTMODE  g_enmMode              = SERIALTESTMODE_LOOPBACK;
     178/** Random number generator. */
     179static RTRAND          g_hRand                = NIL_RTRAND;
    151180/** The serial port handle. */
    152 static RTSERIALPORT    g_hSerialPort         = NIL_RTSERIALPORT;
     181static RTSERIALPORT    g_hSerialPort          = NIL_RTSERIALPORT;
    153182/** The loopback serial port handle if configured. */
    154 static RTSERIALPORT    g_hSerialPortLoopback = NIL_RTSERIALPORT;
     183static RTSERIALPORT    g_hSerialPortSecondary = NIL_RTSERIALPORT;
    155184/** Number of bytes to transmit for read/write tests. */
    156 static size_t          g_cbTx                = _1M;
     185static size_t          g_cbTx                 = _1M;
    157186/** The config used. */
    158187static RTSERIALPORTCFG g_SerialPortCfg =
     
    325354
    326355
     356DECLINLINE(bool) serialTestRndTrue(void)
     357{
     358    return RTRandAdvU32Ex(g_hRand, 0, 1) == 1;
     359}
     360
    327361/**
    328362 * Runs a simple read/write test.
     
    407441    tsRuntime /= 1000; /* Seconds */
    408442    RTTestValue(pSerialTest->hTest, "Throughput", g_cbTx / tsRuntime, RTTESTUNIT_BYTES_PER_SEC);
     443
     444    return rc;
     445}
     446
     447
     448/**
     449 * Tests setting status lines and getting notified about status line changes.
     450 *
     451 * @returns IPRT status code.
     452 * @param   pSerialTest         The serial test configuration.
     453 */
     454static DECLCALLBACK(int) serialTestRunStsLines(PSERIALTEST pSerialTest)
     455{
     456    int rc = VINF_SUCCESS;
     457
     458    if (g_enmMode == SERIALTESTMODE_LOOPBACK)
     459    {
     460        uint32_t fStsLinesQueriedOld = 0;
     461
     462        rc = RTSerialPortChgStatusLines(pSerialTest->hSerialPort,
     463                                        RTSERIALPORT_CHG_STS_LINES_F_RTS | RTSERIALPORT_CHG_STS_LINES_F_DTR,
     464                                        0);
     465        if (RT_SUCCESS(rc))
     466        {
     467            rc = RTSerialPortQueryStatusLines(pSerialTest->hSerialPort, &fStsLinesQueriedOld);
     468            if (RT_SUCCESS(rc))
     469            {
     470                /* Everything should be clear at this stage. */
     471                if (!fStsLinesQueriedOld)
     472                {
     473                    uint32_t fStsLinesSetOld = 0;
     474
     475                    for (uint32_t i = 0; i < SERIALTEST_STS_LINE_TOGGLE_COUNT; i++)
     476                    {
     477                        uint32_t fStsLinesSet = 0;
     478                        uint32_t fStsLinesClear = 0;
     479
     480                        /* Change RTS? */
     481                        if (serialTestRndTrue())
     482                        {
     483                            /* Clear, if set previously otherwise set it. */
     484                            if (fStsLinesSetOld & RTSERIALPORT_CHG_STS_LINES_F_RTS)
     485                                fStsLinesClear |= RTSERIALPORT_CHG_STS_LINES_F_RTS;
     486                            else
     487                                fStsLinesSet   |= RTSERIALPORT_CHG_STS_LINES_F_RTS;
     488                        }
     489
     490                        /* Change DTR? */
     491                        if (serialTestRndTrue())
     492                        {
     493                            /* Clear, if set previously otherwise set it. */
     494                            if (fStsLinesSetOld & RTSERIALPORT_CHG_STS_LINES_F_DTR)
     495                                fStsLinesClear |= RTSERIALPORT_CHG_STS_LINES_F_DTR;
     496                            else
     497                                fStsLinesSet   |= RTSERIALPORT_CHG_STS_LINES_F_DTR;
     498                        }
     499
     500                        rc = RTSerialPortChgStatusLines(pSerialTest->hSerialPort, fStsLinesClear, fStsLinesSet);
     501                        if (RT_FAILURE(rc))
     502                        {
     503                            RTTestFailed(g_hTest, "Changing status lines failed with %Rrc on iteration %u (fSet=%#x fClear=%#x)\n",
     504                                         rc, i, fStsLinesSet, fStsLinesClear);
     505                            break;
     506                        }
     507
     508                        /* Wait for status line monitor event. */
     509                        uint32_t fEvtsRecv = 0;
     510                        rc = RTSerialPortEvtPoll(pSerialTest->hSerialPort, RTSERIALPORT_EVT_F_STATUS_LINE_CHANGED,
     511                                                 &fEvtsRecv, RT_MS_1SEC);
     512                        if (   RT_FAILURE(rc)
     513                            && (rc != VERR_TIMEOUT && !fStsLinesSet && !fStsLinesClear))
     514                        {
     515                            RTTestFailed(g_hTest, "Waiting for status line change failed with %Rrc on iteration %u\n",
     516                                         rc, i);
     517                            break;
     518                        }
     519
     520                        uint32_t fStsLinesQueried = 0;
     521                        rc = RTSerialPortQueryStatusLines(pSerialTest->hSerialPort, &fStsLinesQueried);
     522                        if (RT_FAILURE(rc))
     523                        {
     524                            RTTestFailed(g_hTest, "Querying status lines failed with %Rrc on iteration %u\n",
     525                                         rc, i);
     526                            break;
     527                        }
     528
     529                        /* Compare expected and real result. */
     530                        if (   (fStsLinesQueried & RTSERIALPORT_STS_LINE_DSR)
     531                            != (fStsLinesQueriedOld & RTSERIALPORT_STS_LINE_DSR))
     532                        {
     533                            if (   (fStsLinesQueried & RTSERIALPORT_STS_LINE_DSR)
     534                                && !(fStsLinesSet & RTSERIALPORT_CHG_STS_LINES_F_DTR))
     535                                RTTestFailed(g_hTest, "DSR line got set when it shouldn't be on iteration %u\n",
     536                                             rc, i);
     537                            else if (   !(fStsLinesQueried & RTSERIALPORT_STS_LINE_DSR)
     538                                     && !(fStsLinesClear & RTSERIALPORT_CHG_STS_LINES_F_DTR))
     539                                RTTestFailed(g_hTest, "DSR line got cleared when it shouldn't be on iteration %u\n",
     540                                             rc, i);
     541                        }
     542                        else if (   (fStsLinesSet & RTSERIALPORT_CHG_STS_LINES_F_DTR)
     543                                 || (fStsLinesClear & RTSERIALPORT_CHG_STS_LINES_F_DTR))
     544                                RTTestFailed(g_hTest, "DSR line didn't change when it should have on iteration %u\n",
     545                                             rc, i);
     546
     547                        if (   (fStsLinesQueried & RTSERIALPORT_STS_LINE_DCD)
     548                            != (fStsLinesQueriedOld & RTSERIALPORT_STS_LINE_DCD))
     549                        {
     550                            if (   (fStsLinesQueried & RTSERIALPORT_STS_LINE_DCD)
     551                                && !(fStsLinesSet & RTSERIALPORT_CHG_STS_LINES_F_DTR))
     552                                RTTestFailed(g_hTest, "DCD line got set when it shouldn't be on iteration %u\n",
     553                                             rc, i);
     554                            else if (   !(fStsLinesQueried & RTSERIALPORT_STS_LINE_DCD)
     555                                     && !(fStsLinesClear & RTSERIALPORT_CHG_STS_LINES_F_DTR))
     556                                RTTestFailed(g_hTest, "DCD line got cleared when it shouldn't be on iteration %u\n",
     557                                             rc, i);
     558                        }
     559                        else if (   (fStsLinesSet & RTSERIALPORT_CHG_STS_LINES_F_DTR)
     560                                 || (fStsLinesClear & RTSERIALPORT_CHG_STS_LINES_F_DTR))
     561                                RTTestFailed(g_hTest, "DSR line didn't change when it should have on iteration %u\n",
     562                                             rc, i);
     563
     564                        if (   (fStsLinesQueried & RTSERIALPORT_STS_LINE_CTS)
     565                            != (fStsLinesQueriedOld & RTSERIALPORT_STS_LINE_CTS))
     566                        {
     567                            if (   (fStsLinesQueried & RTSERIALPORT_STS_LINE_CTS)
     568                                && !(fStsLinesSet & RTSERIALPORT_CHG_STS_LINES_F_RTS))
     569                                RTTestFailed(g_hTest, "CTS line got set when it shouldn't be on iteration %u\n",
     570                                             rc, i);
     571                            else if (   !(fStsLinesQueried & RTSERIALPORT_STS_LINE_CTS)
     572                                     && !(fStsLinesClear & RTSERIALPORT_CHG_STS_LINES_F_RTS))
     573                                RTTestFailed(g_hTest, "CTS line got cleared when it shouldn't be on iteration %u\n",
     574                                             rc, i);
     575                        }
     576                        else if (   (fStsLinesSet & RTSERIALPORT_CHG_STS_LINES_F_RTS)
     577                                 || (fStsLinesClear & RTSERIALPORT_CHG_STS_LINES_F_RTS))
     578                                RTTestFailed(g_hTest, "CTS line didn't change when it should have on iteration %u\n",
     579                                             rc, i);
     580
     581                        if (RTTestErrorCount(g_hTest) > 0)
     582                            break;
     583
     584                        fStsLinesSetOld |= fStsLinesSet;
     585                        fStsLinesSetOld &= ~fStsLinesClear;
     586                        fStsLinesQueriedOld = fStsLinesQueried;
     587                    }
     588                }
     589                else
     590                    RTTestFailed(g_hTest, "Status lines active which should be clear (%#x, but expected %#x)\n",
     591                                 fStsLinesQueriedOld, 0);
     592            }
     593            else
     594                RTTestFailed(g_hTest, "Querying status lines failed with %Rrc\n", rc);
     595        }
     596        else
     597            RTTestFailed(g_hTest, "Clearing status lines failed with %Rrc\n", rc);
     598    }
     599    else
     600        rc = VERR_NOT_IMPLEMENTED;
    409601
    410602    return rc;
     
    524716                pszHelp = "Use the given stop bitcount, valid are: 1, 1.5, 2";
    525717                break;
     718            case 'm':
     719                pszHelp = "Mode of the serial port, valid are: loopback, secondary, external";
     720                break;
    526721            case 'l':
    527                 pszHelp = "Use the given serial port device as the loopback device";
     722                pszHelp = "Use the given serial port device as the secondary device";
    528723                break;
    529724            case 't':
     
    557752     */
    558753    const char *pszDevice = NULL;
    559     const char *pszDeviceLoopback = NULL;
     754    const char *pszDeviceSecondary = NULL;
    560755    PSERIALTESTDESC paTests = NULL;
    561756
     
    574769                break;
    575770            case 'l':
    576                 pszDeviceLoopback = ValueUnion.psz;
     771                pszDeviceSecondary = ValueUnion.psz;
    577772                break;
    578773            case 'b':
     
    624819                }
    625820                break;
     821            case 'm':
     822                if (!RTStrICmp(ValueUnion.psz, "loopback"))
     823                    g_enmMode = SERIALTESTMODE_LOOPBACK;
     824                else if (!RTStrICmp(ValueUnion.psz, "secondary"))
     825                    g_enmMode = SERIALTESTMODE_SECONDARY;
     826                else if (!RTStrICmp(ValueUnion.psz, "external"))
     827                    g_enmMode = SERIALTESTMODE_EXTERNAL;
     828                else
     829                {
     830                    RTPrintf("Unknown serial test mode \"%s\" given\n", ValueUnion.psz);
     831                    return RTEXITCODE_FAILURE;
     832                }
     833                break;
    626834            case 't':
    627835                paTests = serialTestSelectFromCmdLine(ValueUnion.psz);
     
    637845    }
    638846
     847    if (g_enmMode == SERIALTESTMODE_SECONDARY && !pszDeviceSecondary)
     848    {
     849        RTPrintf("Mode set to secondary device but no secondary device given\n");
     850        return RTEXITCODE_FAILURE;
     851    }
     852
    639853    if (!paTests)
    640854    {
     
    648862        memcpy(paTests, &g_aSerialTests[0], RT_ELEMENTS(g_aSerialTests) * sizeof(SERIALTESTDESC));
    649863    }
     864
     865    rc = RTRandAdvCreateParkMiller(&g_hRand);
     866    if (RT_FAILURE(rc))
     867    {
     868        RTPrintf("Failed to create random number generator: %Rrc\n");
     869        return RTEXITCODE_FAILURE;
     870    }
     871
     872    rc = RTRandAdvSeed(g_hRand, 0x123456789abcdef);
     873    AssertRC(rc);
    650874
    651875    /*
     
    664888        if (RT_SUCCESS(rc))
    665889        {
    666             if (pszDeviceLoopback)
     890            if (g_enmMode == SERIALTESTMODE_SECONDARY)
    667891            {
    668                 RTTestSub(g_hTest, "Opening loopback device");
    669                 rc = RTSerialPortOpen(&g_hSerialPortLoopback, pszDeviceLoopback, fFlags);
     892                RTTestSub(g_hTest, "Opening secondary device");
     893                rc = RTSerialPortOpen(&g_hSerialPortSecondary, pszDeviceSecondary, fFlags);
    670894                if (RT_FAILURE(rc))
    671                     RTTestFailed(g_hTest, "Opening loopback device \"%s\" failed with %Rrc\n", pszDevice, rc);
     895                    RTTestFailed(g_hTest, "Opening secondary device \"%s\" failed with %Rrc\n", pszDevice, rc);
    672896            }
    673897
     
    679903                if (RT_SUCCESS(rc))
    680904                {
    681                     if (pszDeviceLoopback)
     905                    if (g_enmMode == SERIALTESTMODE_SECONDARY)
    682906                    {
    683                         RTTestSub(g_hTest, "Setting serial port configuration for loopback device");
    684                         rc = RTSerialPortCfgSet(g_hSerialPortLoopback, &g_SerialPortCfg, NULL);
     907                        RTTestSub(g_hTest, "Setting serial port configuration for secondary device");
     908                        rc = RTSerialPortCfgSet(g_hSerialPortSecondary, &g_SerialPortCfg, NULL);
    685909                        if (RT_FAILURE(rc))
    686                             RTTestFailed(g_hTest, "Setting configuration of loopback device \"%s\" failed with %Rrc\n", pszDevice, rc);
     910                            RTTestFailed(g_hTest, "Setting configuration of secondary device \"%s\" failed with %Rrc\n", pszDevice, rc);
    687911                    }
    688912
     
    700924                            RTTestSub(g_hTest, pTest->pszDesc);
    701925                            rc = pTest->pfnRun(&Test);
    702                             if (RT_FAILURE(rc))
    703                                 RTTestFailed(g_hTest, "Running test \"%s\" failed with %Rrc\n", pTest->pszId, rc);
     926                            if (   RT_FAILURE(rc)
     927                                || RTTestErrorCount(g_hTest) > 0)
     928                                RTTestFailed(g_hTest, "Running test \"%s\" failed (%Rrc, cErrors=%u)\n",
     929                                             pTest->pszId, rc, RTTestErrorCount(g_hTest));
    704930
    705931                            RTTestSubDone(g_hTest);
     
    720946        RTTestFailed(g_hTest, "No device given on command line\n");
    721947
     948    RTRandAdvDestroy(g_hRand);
    722949    RTMemFree(paTests);
    723950    RTEXITCODE rcExit = RTTestSummaryAndDestroy(g_hTest);
Note: See TracChangeset for help on using the changeset viewer.

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