VirtualBox

Changeset 99392 in vbox for trunk/src/VBox/Main/testcase


Ignore:
Timestamp:
Apr 13, 2023 4:48:07 PM (22 months ago)
Author:
vboxsync
Message:

Guest Control: Completely revamped / overhauled the (now legacy) stream output parsing code and added lots of documentation to it. This way it should be a lot clearer what it's supposed to be doing.

Also, this now should fix some nasty bugs in that area we had in the past especially with some Linux guests (i.e. OL6), which sometimes send output data in a very unsteady manner.

Also overhauled the testcases while at it.

Luckily, this is all host-based code, so older Guest Additions also will benefit from this.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/testcase/tstGuestCtrlParseBuffer.cpp

    r98526 r99392  
    11/* $Id$ */
    22/** @file
    3  * Output stream parsing test cases.
     3 * Tests for VBoxService toolbox output streams.
    44 */
    55
     
    3939
    4040#include <iprt/env.h>
     41#include <iprt/file.h>
    4142#include <iprt/test.h>
     43#include <iprt/rand.h>
    4244#include <iprt/stream.h>
    4345
     
    5052*   Defined Constants And Macros                                                                                                 *
    5153*********************************************************************************************************************************/
    52 #define STR_SIZE(a_sz) RT_STR_TUPLE(a_sz)
     54/** Defines a test entry string size (in bytes). */
     55#define TST_STR_BYTES(a_sz)          (sizeof(a_sz) - 1)
     56/** Defines a test entry string, followed by its size (in bytes). */
     57#define TST_STR_AND_BYTES(a_sz)      a_sz, (sizeof(a_sz) - 1)
     58/** Defines the termination sequence for a single key/value pair. */
     59#define TST_STR_VAL_TRM              GUESTTOOLBOX_STRM_TERM_PAIR_STR
     60/** Defines the termination sequence for a single stream block. */
     61#define TST_STR_BLK_TRM              GUESTTOOLBOX_STRM_TERM_BLOCK_STR
     62/** Defines the termination sequence for the stream. */
     63#define TST_STR_STM_TRM              GUESTTOOLBOX_STRM_TERM_STREAM_STR
    5364
    5465
     
    7182char szUnterm2[] = { 'f', 'o', 'o', '3', '=', 'b', 'a', 'r', '3' };
    7283
     84PRTLOGGER g_pLog = NULL;
     85
     86/**
     87 * Tests single block parsing.
     88 */
    7389static struct
    7490{
     
    8197} g_aTestBlocks[] =
    8298{
    83     /*
    84      * Single object parsing.
    85      * An object is represented by one or multiple key=value pairs which are
    86      * separated by a single "\0". If this termination is missing it will be assumed
    87      * that we need to collect more data to do a successful parsing.
    88      */
    8999    /* Invalid stuff. */
    90     { NULL,                             0,          0,  0,                                         0, VERR_INVALID_POINTER },
    91     { NULL,                             512,        0,  0,                                         0, VERR_INVALID_POINTER },
    92     { "",                               0,          0,  0,                                         0, VERR_INVALID_PARAMETER },
    93     { "",                               0,          0,  0,                                         0, VERR_INVALID_PARAMETER },
    94     { "foo=bar1",                       0,          0,  0,                                         0, VERR_INVALID_PARAMETER },
    95     { "foo=bar2",                       0,          50, 50,                                        0, VERR_INVALID_PARAMETER },
    96     /* Empty buffers. */
    97     { "",                               1,          0,  1,                                         0, VINF_SUCCESS },
    98     { "\0",                             1,          0,  1,                                         0, VINF_SUCCESS },
    99     /* Unterminated values (missing "\0"). */
    100     { STR_SIZE("test1"),                            0,  0,                                         0, VERR_MORE_DATA },
    101     { STR_SIZE("test2="),                           0,  0,                                         0, VERR_MORE_DATA },
    102     { STR_SIZE("test3=test3"),                      0,  0,                                         0, VERR_MORE_DATA },
    103     { STR_SIZE("test4=test4\0t41"),                 0,  sizeof("test4=test4\0") - 1,               1, VERR_MORE_DATA },
    104     { STR_SIZE("test5=test5\0t51=t51"),             0,  sizeof("test5=test5\0") - 1,               1, VERR_MORE_DATA },
    105     /* Next block unterminated. */
    106     { STR_SIZE("t51=t51\0t52=t52\0\0t53=t53"),      0,  sizeof("t51=t51\0t52=t52\0") - 1,          2, VINF_SUCCESS },
    107     { STR_SIZE("test6=test6\0\0t61=t61"),           0,  sizeof("test6=test6\0") - 1,               1, VINF_SUCCESS },
    108     /* Good stuff. */
    109     { STR_SIZE("test61=\0test611=test611\0"),       0,  sizeof("test61=\0test611=test611\0") - 1,  2, VINF_SUCCESS },
    110     { STR_SIZE("test7=test7\0\0"),                  0,  sizeof("test7=test7\0") - 1,               1, VINF_SUCCESS },
    111     { STR_SIZE("test8=test8\0t81=t81\0\0"),         0,  sizeof("test8=test8\0t81=t81\0") - 1,      2, VINF_SUCCESS },
     100    { NULL,                             0,   0,  0,                             0, VERR_INVALID_POINTER },
     101    { NULL,                             512, 0,  0,                             0, VERR_INVALID_POINTER },
     102    { "",                               0,   0,  0,                             0, VERR_INVALID_PARAMETER },
     103    { "",                               0,   0,  0,                             0, VERR_INVALID_PARAMETER },
     104    { "foo=bar1",                       0,   0,  0,                             0, VERR_INVALID_PARAMETER },
     105    { "foo=bar2",                       0,   50, 50,                            0, VERR_INVALID_PARAMETER },
     106    /* Has a empty key (not allowed). */
     107    { TST_STR_AND_BYTES("=test2" TST_STR_VAL_TRM), 0, TST_STR_BYTES(""),        0, VERR_INVALID_PARAMETER },
     108    /* Empty buffers, i.e. nothing to process. */
     109    /* Index 6*/
     110    { "",                               1, 0,  0,                               0, VINF_SUCCESS },
     111    { TST_STR_VAL_TRM,                  1, 0,  0,                               0, VINF_SUCCESS },
     112    /* Stream termination sequence. */
     113    { TST_STR_AND_BYTES(TST_STR_STM_TRM),                                       0,
     114      TST_STR_BYTES    (TST_STR_STM_TRM),                                       0, VINF_EOF },
     115    /* Trash after stream termination sequence (skipped / ignored). */
     116    { TST_STR_AND_BYTES(TST_STR_STM_TRM "trash"),                               0,
     117      TST_STR_BYTES    (TST_STR_STM_TRM "trash"),                               0, VINF_EOF },
     118    { TST_STR_AND_BYTES("a=b" TST_STR_STM_TRM),                                 0,
     119      TST_STR_BYTES    ("a=b" TST_STR_STM_TRM),                                 1, VINF_EOF },
     120    { TST_STR_AND_BYTES("a=b" TST_STR_VAL_TRM "c=d" TST_STR_STM_TRM),           0,
     121      TST_STR_BYTES    ("a=b" TST_STR_VAL_TRM "c=d" TST_STR_STM_TRM),           2, VINF_EOF },
     122    /* Unterminated values (missing separator, i.e. no valid pair). */
     123    { TST_STR_AND_BYTES("test1"), 0,  0,                                        0, VINF_SUCCESS },
     124    /* Has a NULL value (allowed). */
     125    { TST_STR_AND_BYTES("test2=" TST_STR_VAL_TRM),                              0,
     126      TST_STR_BYTES    ("test2="),                                              1, VINF_SUCCESS },
     127    /* One completed pair only. */
     128    { TST_STR_AND_BYTES("test3=test3" TST_STR_VAL_TRM),                         0,
     129      TST_STR_BYTES    ("test3=test3"),                                         1, VINF_SUCCESS },
     130    /* One completed pair, plus an unfinished pair (separator + terminator missing). */
     131    { TST_STR_AND_BYTES("test4=test4" TST_STR_VAL_TRM "t41"),                   0,
     132      TST_STR_BYTES    ("test4=test4" TST_STR_VAL_TRM),                         1, VINF_SUCCESS },
     133    /* Two completed pairs. */
     134    { TST_STR_AND_BYTES("test5=test5" TST_STR_VAL_TRM "t51=t51" TST_STR_VAL_TRM), 0,
     135      TST_STR_BYTES    ("test5=test5" TST_STR_VAL_TRM "t51=t51"),               2, VINF_SUCCESS },
     136    /* One complete block, next block unterminated. */
     137    { TST_STR_AND_BYTES("a51=b51" TST_STR_VAL_TRM "c52=d52" TST_STR_BLK_TRM "e53=f53"), 0,
     138      TST_STR_BYTES    ("a51=b51" TST_STR_VAL_TRM "c52=d52" TST_STR_BLK_TRM),           2, VINF_SUCCESS },
     139    /* Ditto. */
     140    { TST_STR_AND_BYTES("test6=test6" TST_STR_BLK_TRM "t61=t61"),               0,
     141      TST_STR_BYTES    ("test6=test6" TST_STR_BLK_TRM),                         1, VINF_SUCCESS },
     142    /* Two complete pairs with a complete stream. */
     143    { TST_STR_AND_BYTES("test61=" TST_STR_VAL_TRM "test611=test612" TST_STR_STM_TRM), 0,
     144      TST_STR_BYTES    ("test61=" TST_STR_VAL_TRM "test611=test612" TST_STR_STM_TRM), 2, VINF_EOF },
     145    /* One complete block. */
     146    { TST_STR_AND_BYTES("test7=test7" TST_STR_BLK_TRM),                         0,
     147      TST_STR_BYTES     ("test7=test7"),                                        1, VINF_SUCCESS },
     148    /* Ditto. */
     149    { TST_STR_AND_BYTES("test81=test82" TST_STR_VAL_TRM "t81=t82" TST_STR_BLK_TRM), 0,
     150      TST_STR_BYTES    ("test81=test82" TST_STR_VAL_TRM "t81=t82"),             2, VINF_SUCCESS },
    112151    /* Good stuff, but with a second block -- should be *not* taken into account since
    113152     * we're only interested in parsing/handling the first object. */
    114     { STR_SIZE("t9=t9\0t91=t91\0\0t92=t92\0\0"),    0,  sizeof("t9=t9\0t91=t91\0") - 1,            2, VINF_SUCCESS },
     153    { TST_STR_AND_BYTES("t91=t92" TST_STR_VAL_TRM "t93=t94" TST_STR_BLK_TRM "t95=t96" TST_STR_BLK_TRM), 0,
     154      TST_STR_BYTES    ("t91=t92" TST_STR_VAL_TRM "t93=t94" TST_STR_BLK_TRM),   2, VINF_SUCCESS },
    115155    /* Nasty stuff. */
    116156        /* iso 8859-1 encoding (?) of 'aou' all with diaeresis '=f' and 'ao' with diaeresis. */
    117     { STR_SIZE("\xe4\xf6\xfc=\x66\xe4\xf6\0\0"),    0,  sizeof("\xe4\xf6\xfc=\x66\xe4\xf6\0") - 1, 1, VINF_SUCCESS },
     157    { TST_STR_AND_BYTES("1\xe4\xf6\xfc=\x66\xe4\xf6" TST_STR_BLK_TRM),          0,
     158      TST_STR_BYTES    ("1\xe4\xf6\xfc=\x66\xe4\xf6"),                          1, VINF_SUCCESS },
    118159        /* Like above, but after the first '\0' it adds 'ooo=aaa' all letters with diaeresis. */
    119     { STR_SIZE("\xe4\xf6\xfc=\x66\xe4\xf6\0\xf6\xf6\xf6=\xe4\xe4\xe4"),
    120                                                     0,  sizeof("\xe4\xf6\xfc=\x66\xe4\xf6\0") - 1, 1, VERR_MORE_DATA },
    121     /* Some "real world" examples. */
    122     { STR_SIZE("hdr_id=vbt_stat\0hdr_ver=1\0name=foo.txt\0\0"), 0, sizeof("hdr_id=vbt_stat\0hdr_ver=1\0name=foo.txt\0") - 1,
    123                                                                                                                                           3, VINF_SUCCESS }
     160    { TST_STR_AND_BYTES("2\xe4\xf6\xfc=\x66\xe4\xf6" TST_STR_VAL_TRM "\xf6\xf6\xf6=\xe4\xe4\xe4"), 0,
     161      TST_STR_BYTES    ("2\xe4\xf6\xfc=\x66\xe4\xf6" TST_STR_VAL_TRM),                             1, VINF_SUCCESS },
     162    /* Some "real world" examples from VBoxService toolbox. */
     163    { TST_STR_AND_BYTES("hdr_id=vbt_stat" TST_STR_VAL_TRM "hdr_ver=1" TST_STR_VAL_TRM "name=foo.txt" TST_STR_BLK_TRM), 0,
     164      TST_STR_BYTES    ("hdr_id=vbt_stat" TST_STR_VAL_TRM "hdr_ver=1" TST_STR_VAL_TRM "name=foo.txt"),                 3, VINF_SUCCESS }
    124165};
    125166
     167/**
     168 * Tests parsing multiple stream blocks.
     169 *
     170 * Same parsing behavior as for the tests above apply.
     171 */
    126172static struct
    127173{
     174    /** Stream data. */
    128175    const char *pbData;
     176    /** Size of stream data (in bytes). */
    129177    size_t      cbData;
    130178    /** Number of data blocks retrieved. These are separated by "\0\0". */
     
    135183{
    136184    /* No blocks. */
    137     { "\0\0\0\0",                                      sizeof("\0\0\0\0"),                                0, VERR_NO_DATA },
     185    { "", sizeof(""), 0, VINF_SUCCESS },
     186    /* Empty block (no key/value pairs), will not be accounted. */
     187    { TST_STR_STM_TRM,
     188      TST_STR_BYTES(TST_STR_STM_TRM),                                           0, VINF_EOF },
    138189    /* Good stuff. */
    139     { "\0b1=b1\0\0",                                   sizeof("\0b1=b1\0\0"),                             1, VERR_NO_DATA },
    140     { "b1=b1\0\0",                                     sizeof("b1=b1\0\0"),                               1, VERR_NO_DATA },
    141     { "b1=b1\0b2=b2\0\0",                              sizeof("b1=b1\0b2=b2\0\0"),                        1, VERR_NO_DATA },
    142     { "b1=b1\0b2=b2\0\0\0",                            sizeof("b1=b1\0b2=b2\0\0\0"),                      1, VERR_NO_DATA }
     190    { TST_STR_AND_BYTES(TST_STR_VAL_TRM "b1=b2" TST_STR_STM_TRM),               1, VINF_EOF },
     191    { TST_STR_AND_BYTES("b3=b31" TST_STR_STM_TRM),                              1, VINF_EOF },
     192    { TST_STR_AND_BYTES("b4=b41" TST_STR_BLK_TRM "b51=b61" TST_STR_STM_TRM),    2, VINF_EOF },
     193    { TST_STR_AND_BYTES("b5=b51" TST_STR_VAL_TRM "b61=b71" TST_STR_STM_TRM),    1, VINF_EOF }
    143194};
    144195
    145 int manualTest(void)
    146 {
    147     int rc = VINF_SUCCESS;
    148     static struct
     196/**
     197 * Reads and parses the stream from a given file.
     198 *
     199 * @returns RTEXITCODE
     200 * @param   pszFile             Absolute path to file to parse.
     201 */
     202static int tstReadFromFile(const char *pszFile)
     203{
     204    RTFILE fh;
     205    int rc = RTFileOpen(&fh, pszFile, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
     206    AssertRCReturn(rc, RTEXITCODE_FAILURE);
     207
     208    size_t cbFileSize;
     209    rc = RTFileQuerySize(fh, &cbFileSize);
     210    AssertRCReturn(rc, RTEXITCODE_FAILURE);
     211
     212    GuestToolboxStream      stream;
     213    GuestToolboxStreamBlock block;
     214
     215    size_t cPairs = 0;
     216    size_t cBlocks = 0;
     217
     218    unsigned aToRead[] = { 256, 23, 13 };
     219    unsigned i = 0;
     220
     221    size_t cbToRead = cbFileSize;
     222
     223    for (unsigned a = 0; a < 32; a++)
    149224    {
    150         const char *pbData;
    151         size_t      cbData;
    152         uint32_t    offStart;
    153         uint32_t    offAfter;
    154         uint32_t    cMapElements;
    155         int         iResult;
    156     } const s_aTest[] =
    157     {
    158         { "test5=test5\0t51=t51",           sizeof("test5=test5\0t51=t51"),                            0,  sizeof("test5=test5\0") - 1,                   1, VERR_MORE_DATA },
    159         { "\0\0test5=test5\0t51=t51",       sizeof("\0\0test5=test5\0t51=t51"),                        0,  sizeof("\0\0test5=test5\0") - 1,               1, VERR_MORE_DATA },
    160     };
    161 
    162     for (unsigned iTest = 0; iTest < RT_ELEMENTS(s_aTest); iTest++)
    163     {
    164         RTTestIPrintf(RTTESTLVL_DEBUG, "Manual test #%d\n", iTest);
    165 
    166         GuestToolboxStream stream;
    167         rc = stream.AddData((BYTE *)s_aTest[iTest].pbData, s_aTest[iTest].cbData);
    168 
    169         for (;;)
     225        uint8_t buf[_64K];
     226        do
    170227        {
    171             GuestToolboxStreamBlock block;
     228            size_t cbChunk = RT_MIN(cbToRead, i < RT_ELEMENTS(aToRead) ? aToRead[i++] : RTRandU64Ex(8, RT_MIN(sizeof(buf), 64)));
     229            if (cbChunk > cbToRead)
     230                cbChunk = cbToRead;
     231            if (cbChunk)
     232            {
     233                RTTestIPrintf(RTTESTLVL_DEBUG, "Reading %zu bytes (of %zu left) ...\n", cbChunk, cbToRead);
     234
     235                size_t cbRead;
     236                rc = RTFileRead(fh, &buf, cbChunk, &cbRead);
     237                AssertRCBreak(rc);
     238
     239                if (!cbRead)
     240                    continue;
     241
     242                cbToRead -= cbRead;
     243
     244                rc = stream.AddData((BYTE *)buf, cbRead);
     245                AssertRCBreak(rc);
     246            }
     247
    172248            rc = stream.ParseBlock(block);
    173             RTTestIPrintf(RTTESTLVL_DEBUG, "\tReturned with rc=%Rrc, numItems=%ld\n",
    174                           rc, block.GetCount());
    175 
    176             if (block.GetCount())
    177                 break;
    178         }
     249            Assert(rc != VERR_INVALID_PARAMETER);
     250            RTTestIPrintf(RTTESTLVL_DEBUG, "Parsing ended with %Rrc\n", rc);
     251            if (block.IsComplete())
     252            {
     253                /* Sanity checks; disable this if you parse anything else but fsinfo output from VBoxService toolbox. */
     254                //Assert(block.GetString("name") != NULL);
     255
     256                cPairs += block.GetCount();
     257                cBlocks = stream.GetBlocks();
     258                block.Clear();
     259            }
     260        } while (VINF_SUCCESS == rc /* Might also be VINF_EOF when finished */);
     261
     262        RTTestIPrintf(RTTESTLVL_ALWAYS, "Total %zu blocks + %zu pairs\n", cBlocks, cPairs);
     263
     264        /* Reset. */
     265        RTFileSeek(fh, 0, RTFILE_SEEK_BEGIN, NULL);
     266        cbToRead = cbFileSize;
     267        cPairs = 0;
     268        cBlocks = 0;
     269        block.Clear();
     270        stream.Destroy();
    179271    }
    180272
    181     return rc;
     273    int rc2 = RTFileClose(fh);
     274    if (RT_SUCCESS(rc))
     275        rc = rc2;
     276
     277    return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
    182278}
    183279
    184 int main()
     280int main(int argc, char **argv)
    185281{
    186282    RTTEST hTest;
     
    189285        return rcExit;
    190286    RTTestBanner(hTest);
     287
     288#ifdef DEBUG
     289    RTUINT fFlags = RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG;
     290#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
     291    fFlags |= RTLOGFLAGS_USECRLF;
     292#endif
     293    static const char * const s_apszLogGroups[] = VBOX_LOGGROUP_NAMES;
     294    int rc = RTLogCreate(&g_pLog, fFlags, "guest_control.e.l.l2.l3.f", NULL,
     295                         RT_ELEMENTS(s_apszLogGroups), s_apszLogGroups, RTLOGDEST_STDOUT, NULL /*"vkat-release.log"*/);
     296    AssertRCReturn(rc, rc);
     297    RTLogSetDefaultInstance(g_pLog);
     298#endif
     299
     300    if (argc > 1)
     301        return tstReadFromFile(argv[1]);
    191302
    192303    RTTestIPrintf(RTTESTLVL_DEBUG, "Initializing COM...\n");
     
    198309    }
    199310
    200 #ifdef DEBUG_andy
    201     int rc = manualTest();
    202     if (RT_FAILURE(rc))
    203         return RTEXITCODE_FAILURE;
    204 #endif
    205 
    206     AssertCompile(sizeof("sizecheck")   == 10);
    207     AssertCompile(sizeof("off=rab")     == 8);
    208     AssertCompile(sizeof("off=rab\0\0") == 10);
    209 
    210     RTTestSub(hTest, "Lines");
     311    AssertCompile(TST_STR_BYTES("1")           == 1);
     312    AssertCompile(TST_STR_BYTES("sizecheck")   == 9);
     313    AssertCompile(TST_STR_BYTES("off=rab")     == 7);
     314    AssertCompile(TST_STR_BYTES("off=rab\0\0") == 9);
     315
     316    RTTestSub(hTest, "Blocks");
     317
     318    RTTestDisableAssertions(hTest);
     319
    211320    for (unsigned iTest = 0; iTest < RT_ELEMENTS(g_aTestBlocks); iTest++)
    212321    {
    213         RTTestIPrintf(RTTESTLVL_DEBUG, "=> Test #%u\n", iTest);
     322        RTTestIPrintf(RTTESTLVL_DEBUG, "=> Block test #%u:\n'%.*RhXd\n", iTest, g_aTestBlocks[iTest].cbData, g_aTestBlocks[iTest].pbData);
    214323
    215324        GuestToolboxStream stream;
    216         if (RT_FAILURE(g_aTestBlocks[iTest].iResult))
    217             RTTestDisableAssertions(hTest);
    218325        int iResult = stream.AddData((BYTE *)g_aTestBlocks[iTest].pbData, g_aTestBlocks[iTest].cbData);
    219         if (RT_FAILURE(g_aTestBlocks[iTest].iResult))
    220             RTTestRestoreAssertions(hTest);
    221326        if (RT_SUCCESS(iResult))
    222327        {
     
    224329            iResult = stream.ParseBlock(curBlock);
    225330            if (iResult != g_aTestBlocks[iTest].iResult)
    226                 RTTestFailed(hTest, "Block #%u: Returned %Rrc, expected %Rrc", iTest, iResult, g_aTestBlocks[iTest].iResult);
     331                RTTestFailed(hTest, "Block #%u: Returned %Rrc, expected %Rrc\n", iTest, iResult, g_aTestBlocks[iTest].iResult);
    227332            else if (stream.GetOffset() != g_aTestBlocks[iTest].offAfter)
    228                 RTTestFailed(hTest, "Block #%uOffset %zu wrong, expected %u\n",
    229                              iTest, stream.GetOffset(), g_aTestBlocks[iTest].offAfter);
     333                RTTestFailed(hTest, "Block #%u: Offset %zu wrong ('%#x'), expected %u ('%#x')\n",
     334                             iTest, stream.GetOffset(), g_aTestBlocks[iTest].pbData[stream.GetOffset()],
     335                             g_aTestBlocks[iTest].offAfter, g_aTestBlocks[iTest].pbData[g_aTestBlocks[iTest].offAfter]);
    230336            else if (iResult == VERR_MORE_DATA)
    231337                RTTestIPrintf(RTTESTLVL_DEBUG, "\tMore data (Offset: %zu)\n", stream.GetOffset());
     
    249355                    RTStrmWriteEx(g_pStdOut, &g_aTestBlocks[iTest].pbData[off], cbToWrite - 1, NULL);
    250356            }
     357
     358            if (RTTestIErrorCount())
     359                break;
    251360        }
    252361    }
    253362
    254     RTTestSub(hTest, "Blocks");
     363    RTTestSub(hTest, "Streams");
     364
    255365    for (unsigned iTest = 0; iTest < RT_ELEMENTS(g_aTestStream); iTest++)
    256366    {
    257         RTTestIPrintf(RTTESTLVL_DEBUG, "=> Block test #%u\n", iTest);
     367        RTTestIPrintf(RTTESTLVL_DEBUG, "=> Stream test #%u\n%.*RhXd\n",
     368                      iTest, g_aTestStream[iTest].cbData, g_aTestStream[iTest].pbData);
    258369
    259370        GuestToolboxStream stream;
     
    261372        if (RT_SUCCESS(iResult))
    262373        {
    263             uint32_t cBlocks = 0;
    264             uint8_t uSafeCouunter = 0;
     374            uint32_t cBlocksComplete = 0;
     375            uint8_t  cSafety = 0;
    265376            do
    266377            {
    267378                GuestToolboxStreamBlock curBlock;
    268379                iResult = stream.ParseBlock(curBlock);
    269                 RTTestIPrintf(RTTESTLVL_DEBUG, "Block #%u: Returned with %Rrc", iTest, iResult);
    270                 if (RT_SUCCESS(iResult))
    271                 {
    272                     /* Only count block which have at least one pair. */
    273                     if (curBlock.GetCount())
    274                         cBlocks++;
    275                 }
    276                 if (uSafeCouunter++ > 32)
     380                RTTestIPrintf(RTTESTLVL_DEBUG, "Stream #%u: Returned with %Rrc\n", iTest, iResult);
     381                if (cSafety++ > 8)
    277382                    break;
    278             } while (RT_SUCCESS(iResult));
     383                if (curBlock.IsComplete())
     384                    cBlocksComplete++;
     385            } while (iResult != VINF_EOF);
    279386
    280387            if (iResult != g_aTestStream[iTest].iResult)
    281                 RTTestFailed(hTest, "Block #%uReturned %Rrc, expected %Rrc", iTest, iResult, g_aTestStream[iTest].iResult);
    282             else if (cBlocks != g_aTestStream[iTest].cBlocks)
    283                 RTTestFailed(hTest, "Block #%uReturned %u blocks, expected %u", iTest, cBlocks, g_aTestStream[iTest].cBlocks);
     388                RTTestFailed(hTest, "Stream #%u: Returned %Rrc, expected %Rrc\n", iTest, iResult, g_aTestStream[iTest].iResult);
     389            else if (cBlocksComplete != g_aTestStream[iTest].cBlocks)
     390                RTTestFailed(hTest, "Stream #%u: Returned %u blocks, expected %u\n", iTest, cBlocksComplete, g_aTestStream[iTest].cBlocks);
    284391        }
    285392        else
    286             RTTestFailed(hTest, "Block #%u: Adding data failed with %Rrc", iTest, iResult);
     393            RTTestFailed(hTest, "Stream #%u: Adding data failed with %Rrc\n", iTest, iResult);
     394
     395        if (RTTestIErrorCount())
     396            break;
    287397    }
     398
     399    RTTestRestoreAssertions(hTest);
    288400
    289401    RTTestIPrintf(RTTESTLVL_DEBUG, "Shutting down COM...\n");
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