VirtualBox

Ignore:
Timestamp:
Nov 4, 2008 9:46:13 AM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
38763
Message:

Recommitted r38734: Guest Properties (HostServices and Main): major clean up of the guest property service

Location:
trunk/src/VBox/HostServices/GuestProperties/testcase
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/GuestProperties/testcase/Makefile.kmk

    r13763 r13779  
    2929PROGRAMS += tstGuestPropSvc
    3030tstGuestPropSvc_TEMPLATE = VBOXR3TSTEXE
    31 tstGuestPropSvc_DEFS     = VBOX_WITH_HGCM
    32 tstGuestPropSvc_SOURCES  = tstGuestPropSvc.cpp
     31# The second define here is to ensure that the testcase will run fast, without
     32# waiting for any thread synchronisation.
     33tstGuestPropSvc_DEFS     = VBOX_WITH_HGCM VBOX_GUEST_PROP_TEST_NOTHREAD
     34tstGuestPropSvc_SOURCES  = tstGuestPropSvc.cpp ../service.cpp
    3335tstGuestPropSvc_LIBS     = $(LIB_RUNTIME)
     36
     37# Set this in LocalConfig.kmk if you are working on the guest property service
     38# to automatically run the testcase at build time.
     39ifdef VBOX_RUN_GUEST_PROPERTY_TEST
     40 ifndef VBOX_ONLY_SDK
     41  TESTING  += $(PATH_tstGuestPropSvc)/tstGuestPropSvc.run
     42  OTHERS += $(PATH_tstGuestPropSvc)/tstGuestPropSvc.run
     43$$(PATH_tstGuestPropSvc)/tstGuestPropSvc.run: $$(INSTARGET_tstGuestPropSvc)
     44        $(INSTARGET_tstGuestPropSvc) quiet
     45        $(QUIET)$(APPEND) -t "$@" "done"
     46 endif
     47endif
    3448
    3549endif # VBOX_WITH_TESTCASES
  • trunk/src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp

    r13763 r13779  
    22/** @file
    33 *
    4  * Testcase for the guest property service.  For now, this only tests
    5  * flag conversion.
     4 * Testcase for the guest property service.
    65 */
    76
     
    3130using namespace guestProp;
    3231
    33 /**
    34  * A list of valid flag strings.  The flag conversion functions should accept
    35  * these and convert them from string to a flag type and back without errors.
     32extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable);
     33
     34/** Set a pointer value to an HGCM parameter structure */
     35static void VBoxHGCMParmPtrSet (VBOXHGCMSVCPARM *pParm, void *pv, uint32_t cb)
     36{
     37    pParm->type = VBOX_HGCM_SVC_PARM_PTR;
     38    pParm->u.pointer.addr = pv;
     39    pParm->u.pointer.size = cb;
     40}
     41
     42/** Extract a uint64_t value from an HGCM parameter structure */
     43static int VBoxHGCMParmUInt32Get (VBOXHGCMSVCPARM *pParm, uint32_t *pu32Value)
     44{
     45    if (pParm->type == VBOX_HGCM_SVC_PARM_32BIT)
     46    {
     47        *pu32Value = pParm->u.uint32;
     48        return VINF_SUCCESS;
     49    }
     50
     51    return VERR_INVALID_PARAMETER;
     52}
     53
     54/** Extract a uint64_t value from an HGCM parameter structure */
     55static int VBoxHGCMParmUInt64Get (VBOXHGCMSVCPARM *pParm, uint64_t *pu64Value)
     56{
     57    if (pParm->type == VBOX_HGCM_SVC_PARM_64BIT)
     58    {
     59        *pu64Value = pParm->u.uint64;
     60        return VINF_SUCCESS;
     61    }
     62
     63    return VERR_INVALID_PARAMETER;
     64}
     65
     66/** Simple call handle structure for the guest call completion callback */
     67struct VBOXHGCMCALLHANDLE_TYPEDEF
     68{
     69    /** Where to store the result code */
     70    int32_t rc;
     71};
     72
     73/** Call completion callback for guest calls. */
     74static void callComplete(VBOXHGCMCALLHANDLE callHandle, int32_t rc)
     75{
     76    callHandle->rc = rc;
     77}
     78
     79/**
     80 * Initialise the HGCM service table as much as we need to start the
     81 * service
     82 * @param  pTable the table to initialise
     83 */
     84void initTable(VBOXHGCMSVCFNTABLE *pTable, VBOXHGCMSVCHELPERS *pHelpers)
     85{
     86    pTable->cbSize = sizeof (VBOXHGCMSVCFNTABLE);
     87    pTable->u32Version = VBOX_HGCM_SVC_VERSION;
     88    pHelpers->pfnCallComplete = callComplete;
     89    pTable->pHelpers = pHelpers;
     90}
     91
     92/**
     93 * A list of valid flag strings for testConvertFlags.  The flag conversion
     94 * functions should accept these and convert them from string to a flag type
     95 * and back without errors.
    3696 */
    3797struct flagStrings
     
    44104validFlagStrings[] =
    45105{
    46     { "", "" },
     106    { "  ", "" },
    47107    { "transient, ", "TRANSIENT" },
    48     { "  rdOnLyHOST, transIENT  ,     READONLY    ", "TRANSIENT, READONLY" }
    49 };
    50 
     108    { "  rdOnLyHOST, transIENT  ,     READONLY    ", "TRANSIENT, READONLY" },
     109    { " rdonlyguest", "RDONLYGUEST" },
     110    { "rdonlyhost     ", "RDONLYHOST" }
     111};
     112
     113/**
     114 * A list of invalid flag strings for testConvertFlags.  The flag conversion
     115 * functions should reject these.
     116 */
     117const char *invalidFlagStrings[] =
     118{
     119    "RDONLYHOST,,",
     120    "  TRANSIENT READONLY"
     121};
     122
     123/**
     124 * Test the flag conversion functions.
     125 * @returns iprt status value to indicate whether the test went as expected.
     126 * @note    prints its own diagnostic information to stdout.
     127 */
    51128int testConvertFlags()
    52129{
     
    55132    for (unsigned i = 0; i < RT_ELEMENTS(validFlagStrings) && RT_SUCCESS(rc); ++i)
    56133    {
    57         char szFlagBuffer[MAX_FLAGS_LEN];
     134        char szFlagBuffer[MAX_FLAGS_LEN * 2];
    58135        uint32_t fFlags;
    59136        rc = validateFlags(validFlagStrings[i].pcszIn, &fFlags);
    60137        if (RT_FAILURE(rc))
    61             RTPrintf("tstGuestPropSvc: FAILURE - Failed to validate flag string %s.\n", validFlagStrings[i].pcszIn);
     138            RTPrintf("tstGuestPropSvc: FAILURE - Failed to validate flag string '%s'.\n", validFlagStrings[i].pcszIn);
    62139        if (RT_SUCCESS(rc))
    63140        {
    64141            rc = writeFlags(fFlags, szFlagBuffer);
    65142            if (RT_FAILURE(rc))
    66                 RTPrintf("tstGuestPropSvc: FAILURE - Failed to convert flag string %s back to a string.\n",
     143                RTPrintf("tstGuestPropSvc: FAILURE - Failed to convert flag string '%s' back to a string.\n",
    67144                            validFlagStrings[i].pcszIn);
    68145        }
    69146        if (RT_SUCCESS(rc) && (strlen(szFlagBuffer) > MAX_FLAGS_LEN - 1))
    70147        {
    71             RTPrintf("tstGuestPropSvc: FAILURE - String %s converts back to a flag string which is too long.\n",
     148            RTPrintf("tstGuestPropSvc: FAILURE - String '%s' converts back to a flag string which is too long.\n",
    72149                        validFlagStrings[i].pcszIn);
    73150            rc = VERR_TOO_MUCH_DATA;
     
    75152        if (RT_SUCCESS(rc) && (strcmp(szFlagBuffer, validFlagStrings[i].pcszOut) != 0))
    76153        {
    77             RTPrintf("tstGuestPropSvc: FAILURE - String %s converts back to %s instead of to %s\n",
     154            RTPrintf("tstGuestPropSvc: FAILURE - String '%s' converts back to '%s' instead of to '%s'\n",
    78155                        validFlagStrings[i].pcszIn, szFlagBuffer,
    79156                        validFlagStrings[i].pcszOut);
     
    81158        }
    82159    }
     160    if (RT_SUCCESS(rc))
     161    {
     162        RTPrintf("Testing rejection of invalid flags strings.\n");
     163        for (unsigned i = 0; i < RT_ELEMENTS(invalidFlagStrings) && RT_SUCCESS(rc); ++i)
     164        {
     165            uint32_t fFlags;
     166            /* This is required to fail. */
     167            if (RT_SUCCESS(validateFlags(invalidFlagStrings[i], &fFlags)))
     168            {
     169                RTPrintf("String '%s' was incorrectly accepted as a valid flag string.\n",
     170                         invalidFlagStrings[i]);
     171                rc = VERR_PARSE_ERROR;
     172            }
     173        }
     174    }
     175    if (RT_SUCCESS(rc))
     176    {
     177        char szFlagBuffer[MAX_FLAGS_LEN * 2];
     178        uint32_t u32BadFlags = ALLFLAGS << 1;
     179        RTPrintf("Testing rejection of an invalid flags field.\n");
     180        /* This is required to fail. */
     181        if (RT_SUCCESS(writeFlags(u32BadFlags, szFlagBuffer)))
     182        {
     183            RTPrintf("Flags 0x%x were incorrectly written out as '%.*s'\n",
     184                     u32BadFlags, MAX_FLAGS_LEN, szFlagBuffer);
     185            rc = VERR_PARSE_ERROR;
     186        }
     187    }
    83188    return rc;
    84189}
    85190
     191/**
     192 * List of property names for testSetPropsHost.
     193 */
     194const char *apcszNameBlock[] =
     195{
     196    "test/name/",
     197    "test name",
     198    "TEST NAME",
     199    "/test/name",
     200    NULL
     201};
     202
     203/**
     204 * List of property values for testSetPropsHost.
     205 */
     206const char *apcszValueBlock[] =
     207{
     208    "test/value/",
     209    "test value",
     210    "TEST VALUE",
     211    "/test/value",
     212    NULL
     213};
     214
     215/**
     216 * List of property timestamps for testSetPropsHost.
     217 */
     218uint64_t au64TimestampBlock[] =
     219{
     220    0, 999, 999999, 999999999999, 0
     221};
     222
     223/**
     224 * List of property flags for testSetPropsHost.
     225 */
     226const char *apcszFlagsBlock[] =
     227{
     228    "",
     229    "readonly, transient",
     230    "RDONLYHOST",
     231    "RdOnlyGuest",
     232    NULL
     233};
     234
     235/**
     236 * Test the SET_PROPS_HOST function.
     237 * @returns iprt status value to indicate whether the test went as expected.
     238 * @note    prints its own diagnostic information to stdout.
     239 */
     240int testSetPropsHost(VBOXHGCMSVCFNTABLE *ptable)
     241{
     242    int rc = VINF_SUCCESS;
     243    RTPrintf("Testing the SET_PROPS_HOST call.\n");
     244    if (!VALID_PTR(ptable->pfnHostCall))
     245    {
     246        RTPrintf("Invalid pfnHostCall() pointer\n");
     247        rc = VERR_INVALID_POINTER;
     248    }
     249    if (RT_SUCCESS(rc))
     250    {
     251        VBOXHGCMSVCPARM paParms[4];
     252        VBoxHGCMParmPtrSet(&paParms[0], (void *) apcszNameBlock, 0);
     253        VBoxHGCMParmPtrSet(&paParms[1], (void *) apcszValueBlock, 0);
     254        VBoxHGCMParmPtrSet(&paParms[2], (void *) au64TimestampBlock, 0);
     255        VBoxHGCMParmPtrSet(&paParms[3], (void *) apcszFlagsBlock, 0);
     256        rc = ptable->pfnHostCall(ptable->pvService, SET_PROPS_HOST, 4,
     257                                 paParms);
     258        if (RT_FAILURE(rc))
     259            RTPrintf("SET_PROPS_HOST call failed with rc=%Rrc\n", rc);
     260    }
     261    return rc;
     262}
     263
     264/** Result strings for zeroth enumeration test */
     265static const char *pcchEnumResult0[] =
     266{
     267    "test/name/\0test/value/\0""0\0",
     268    "test name\0test value\0""999\0TRANSIENT, READONLY",
     269    "TEST NAME\0TEST VALUE\0""999999\0RDONLYHOST",
     270    "/test/name\0/test/value\0""999999999999\0RDONLYGUEST",
     271    NULL
     272};
     273
     274/** Result string sizes for zeroth enumeration test */
     275static const size_t cchEnumResult0[] =
     276{
     277    sizeof("test/name/\0test/value/\0""0\0"),
     278    sizeof("test name\0test value\0""999\0TRANSIENT, READONLY"),
     279    sizeof("TEST NAME\0TEST VALUE\0""999999\0RDONLYHOST"),
     280    sizeof("/test/name\0/test/value\0""999999999999\0RDONLYGUEST"),
     281    0
     282};
     283
     284/**
     285 * The size of the buffer returned by the zeroth enumeration test -
     286 * the - 1 at the end is because of the hidden zero terminator
     287 */
     288static const size_t cchEnumBuffer0 =
     289sizeof("test/name/\0test/value/\0""0\0\0"
     290"test name\0test value\0""999\0TRANSIENT, READONLY\0"
     291"TEST NAME\0TEST VALUE\0""999999\0RDONLYHOST\0"
     292"/test/name\0/test/value\0""999999999999\0RDONLYGUEST\0\0\0\0\0") - 1;
     293
     294/** Result strings for first and second enumeration test */
     295static const char *pcchEnumResult1[] =
     296{
     297    "TEST NAME\0TEST VALUE\0""999999\0RDONLYHOST",
     298    "/test/name\0/test/value\0""999999999999\0RDONLYGUEST",
     299    NULL
     300};
     301
     302/** Result string sizes for first and second enumeration test */
     303static const size_t cchEnumResult1[] =
     304{
     305    sizeof("TEST NAME\0TEST VALUE\0""999999\0RDONLYHOST"),
     306    sizeof("/test/name\0/test/value\0""999999999999\0RDONLYGUEST"),
     307    0
     308};
     309
     310/**
     311 * The size of the buffer returned by the first enumeration test -
     312 * the - 1 at the end is because of the hidden zero terminator
     313 */
     314static const size_t cchEnumBuffer1 =
     315sizeof("TEST NAME\0TEST VALUE\0""999999\0RDONLYHOST\0"
     316"/test/name\0/test/value\0""999999999999\0RDONLYGUEST\0\0\0\0\0") - 1;
     317
     318static const struct enumStringStruct
     319{
     320    /** The enumeration pattern to test */
     321    const char *pcszPatterns;
     322    /** The size of the pattern string */
     323    const size_t cchPatterns;
     324    /** The expected enumeration output strings */
     325    const char **ppcchResult;
     326    /** The size of the output strings */
     327    const size_t *pcchResult;
     328    /** The size of the buffer needed for the enumeration */
     329    const size_t cchBuffer;
     330}
     331enumStrings[] =
     332{
     333    {
     334        "", sizeof(""),
     335        pcchEnumResult0,
     336        cchEnumResult0,
     337        cchEnumBuffer0
     338    },
     339    {
     340        "/*\0?E*", sizeof("/*\0?E*"),
     341        pcchEnumResult1,
     342        cchEnumResult1,
     343        cchEnumBuffer1
     344    },
     345    {
     346        "/*|?E*", sizeof("/*|?E*"),
     347        pcchEnumResult1,
     348        cchEnumResult1,
     349        cchEnumBuffer1
     350    }
     351};
     352
     353/**
     354 * Test the ENUM_PROPS_HOST function.
     355 * @returns iprt status value to indicate whether the test went as expected.
     356 * @note    prints its own diagnostic information to stdout.
     357 */
     358int testEnumPropsHost(VBOXHGCMSVCFNTABLE *ptable)
     359{
     360    int rc = VINF_SUCCESS;
     361    RTPrintf("Testing the ENUM_PROPS_HOST call.\n");
     362    if (!VALID_PTR(ptable->pfnHostCall))
     363    {
     364        RTPrintf("Invalid pfnHostCall() pointer\n");
     365        rc = VERR_INVALID_POINTER;
     366    }
     367    for (unsigned i = 0; RT_SUCCESS(rc) && i < RT_ELEMENTS(enumStrings);
     368         ++i)
     369    {
     370        char buffer[2048];
     371        VBOXHGCMSVCPARM paParms[3];
     372        VBoxHGCMParmPtrSet(&paParms[0],
     373                           (void *) enumStrings[i].pcszPatterns,
     374                           enumStrings[i].cchPatterns);
     375        VBoxHGCMParmPtrSet(&paParms[1],
     376                           (void *) buffer,
     377                           enumStrings[i].cchBuffer - 1);
     378        AssertBreakStmt(sizeof(buffer) > enumStrings[i].cchBuffer,
     379                        rc = VERR_INTERNAL_ERROR);
     380        if (RT_SUCCESS(rc))
     381        {
     382            /* This should fail as the buffer is too small. */
     383            int rc2 = ptable->pfnHostCall(ptable->pvService, ENUM_PROPS_HOST,
     384                                          3, paParms);
     385            if (rc2 != VERR_BUFFER_OVERFLOW)
     386            {
     387                RTPrintf("ENUM_PROPS_HOST returned %Rrc instead of VERR_BUFFER_OVERFLOW on too small buffer, pattern number %d\n", rc2, i);
     388                rc = VERR_BUFFER_OVERFLOW;
     389            }
     390            else
     391            {
     392                uint32_t cchBufferActual;
     393                rc = VBoxHGCMParmUInt32Get(&paParms[2], &cchBufferActual);
     394                if (RT_SUCCESS(rc) && cchBufferActual != enumStrings[i].cchBuffer)
     395                {
     396                    RTPrintf("ENUM_PROPS_HOST requested a buffer size of %lu instead of %lu for pattern number %d\n", cchBufferActual, enumStrings[i].cchBuffer, i);
     397                    rc = VERR_OUT_OF_RANGE;
     398                }
     399                else if (RT_FAILURE(rc))
     400                    RTPrintf("ENUM_PROPS_HOST did not return the required buffer size properly for pattern %d\n", i);
     401            }
     402        }
     403        if (RT_SUCCESS(rc))
     404        {
     405            VBoxHGCMParmPtrSet(&paParms[1], (void *) buffer,
     406                               enumStrings[i].cchBuffer);
     407            rc = ptable->pfnHostCall(ptable->pvService, ENUM_PROPS_HOST,
     408                                      3, paParms);
     409            if (RT_FAILURE(rc))
     410                RTPrintf("ENUM_PROPS_HOST call failed for pattern %d with rc=%Rrc\n", i, rc);
     411            else
     412                /* Look for each of the result strings in the buffer which was returned */
     413                for (unsigned j = 0; RT_SUCCESS(rc) && enumStrings[i].ppcchResult[j] != NULL;
     414                     ++j)
     415                {
     416                    bool found = false;
     417                    for (unsigned k = 0; !found && k <   enumStrings[i].cchBuffer
     418                                                       - enumStrings[i].pcchResult[j];
     419                         ++k)
     420                        if (memcmp(buffer + k, enumStrings[i].ppcchResult[j],
     421                            enumStrings[i].pcchResult[j]) == 0)
     422                            found = true;
     423                    if (!found)
     424                    {
     425                        RTPrintf("ENUM_PROPS_HOST did not produce the expected output for pattern %d\n",
     426                                 i);
     427                        rc = VERR_UNRESOLVED_ERROR;
     428                    }
     429                }
     430        }
     431    }
     432    return rc;
     433}
     434
     435/** Array of properties for testing SET_PROP_HOST and _GUEST. */
     436static const struct
     437{
     438    /** Property name */
     439    const char *pcszName;
     440    /** Property value */
     441    const char *pcszValue;
     442    /** Property flags */
     443    const char *pcszFlags;
     444    /** Should this be set as the host or the guest? */
     445    bool isHost;
     446    /** Should we use SET_PROP or SET_PROP_VALUE? */
     447    bool useSetProp;
     448    /** Should this succeed or be rejected with VERR_PERMISSION_DENIED? */
     449    bool isAllowed;
     450}
     451setProperties[] =
     452{
     453    { "Red", "Stop!", "transient", false, true, true },
     454    { "Amber", "Caution!", "", false, false, true },
     455    { "Green", "Go!", "readonly", true, true, true },
     456    { "Blue", "What on earth...?", "", true, false, true },
     457    { "/test/name", "test", "", false, true, false },
     458    { "TEST NAME", "test", "", true, true, false },
     459    { "Green", "gone out...", "", false, false, false },
     460    { "Green", "gone out...", "", true, false, false },
     461    { NULL, NULL, NULL, false, false, false }
     462};
     463
     464/**
     465 * Test the SET_PROP, SET_PROP_VALUE, SET_PROP_HOST and SET_PROP_VALUE_HOST
     466 * functions.
     467 * @returns iprt status value to indicate whether the test went as expected.
     468 * @note    prints its own diagnostic information to stdout.
     469 */
     470int testSetProp(VBOXHGCMSVCFNTABLE *pTable)
     471{
     472    int rc = VINF_SUCCESS;
     473    VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
     474    RTPrintf("Testing the SET_PROP, SET_PROP_VALUE, SET_PROP_HOST and SET_PROP_VALUE_HOST calls.\n");
     475    for (unsigned i = 0; RT_SUCCESS(rc) && (setProperties[i].pcszName != NULL);
     476         ++i)
     477    {
     478        int command = SET_PROP_VALUE;
     479        if (setProperties[i].isHost)
     480        {
     481            if (setProperties[i].useSetProp)
     482                command = SET_PROP_HOST;
     483            else
     484                command = SET_PROP_VALUE_HOST;
     485        }
     486        else if (setProperties[i].useSetProp)
     487            command = SET_PROP;
     488        VBOXHGCMSVCPARM paParms[3];
     489        /* Work around silly constant issues - we ought to allow passing
     490         * constant strings in the hgcm parameters. */
     491        char szName[MAX_NAME_LEN] = "";
     492        char szValue[MAX_VALUE_LEN] = "";
     493        char szFlags[MAX_FLAGS_LEN] = "";
     494        strncat(szName, setProperties[i].pcszName, sizeof(szName));
     495        strncat(szValue, setProperties[i].pcszValue, sizeof(szValue));
     496        strncat(szFlags, setProperties[i].pcszFlags, sizeof(szFlags));
     497        VBoxHGCMParmPtrSet(&paParms[0], szName, strlen(szName) + 1);
     498        VBoxHGCMParmPtrSet(&paParms[1], szValue, strlen(szValue) + 1);
     499        VBoxHGCMParmPtrSet(&paParms[2], szFlags, strlen(szFlags) + 1);
     500        if (setProperties[i].isHost)
     501            callHandle.rc = pTable->pfnHostCall(pTable->pvService, command,
     502                                                setProperties[i].useSetProp
     503                                                    ? 3 : 2, paParms);
     504        else
     505            pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL, command,
     506                            setProperties[i].useSetProp ? 3 : 2, paParms);
     507        if (setProperties[i].isAllowed && RT_FAILURE(callHandle.rc))
     508        {
     509            RTPrintf("Setting property '%s' failed with rc=%Rrc.\n",
     510                     setProperties[i].pcszName, callHandle.rc);
     511            rc = callHandle.rc;
     512        }
     513        else if (   !setProperties[i].isAllowed
     514                 && (callHandle.rc != VERR_PERMISSION_DENIED)
     515                )
     516        {
     517            RTPrintf("Setting property '%s' returned %Rrc instead of VERR_PERMISSION_DENIED.\n",
     518                     setProperties[i].pcszName, callHandle.rc);
     519            rc = VERR_UNRESOLVED_ERROR;
     520        }
     521    }
     522    return rc;
     523}
     524
     525/** Array of properties for testing DEL_PROP_HOST and _GUEST. */
     526static const struct
     527{
     528    /** Property name */
     529    const char *pcszName;
     530    /** Should this be set as the host or the guest? */
     531    bool isHost;
     532    /** Should this succeed or be rejected with VERR_PERMISSION_DENIED? */
     533    bool isAllowed;
     534}
     535delProperties[] =
     536{
     537    { "Red", false, true },
     538    { "Amber", true, true },
     539    { "Red2", false, true },
     540    { "Amber2", true, true },
     541    { "Green", false, false },
     542    { "Green", true, false },
     543    { "/test/name", false, false },
     544    { "TEST NAME", true, false },
     545    { NULL, false, false }
     546};
     547
     548/**
     549 * Test the DEL_PROP, and DEL_PROP_HOST functions.
     550 * @returns iprt status value to indicate whether the test went as expected.
     551 * @note    prints its own diagnostic information to stdout.
     552 */
     553int testDelProp(VBOXHGCMSVCFNTABLE *pTable)
     554{
     555    int rc = VINF_SUCCESS;
     556    VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
     557    RTPrintf("Testing the DEL_PROP and DEL_PROP_HOST calls.\n");
     558    for (unsigned i = 0; RT_SUCCESS(rc) && (delProperties[i].pcszName != NULL);
     559         ++i)
     560    {
     561        int command = DEL_PROP;
     562        if (delProperties[i].isHost)
     563            command = DEL_PROP_HOST;
     564        VBOXHGCMSVCPARM paParms[1];
     565        /* Work around silly constant issues - we ought to allow passing
     566         * constant strings in the hgcm parameters. */
     567        char szName[MAX_NAME_LEN] = "";
     568        strncat(szName, delProperties[i].pcszName, sizeof(szName));
     569        VBoxHGCMParmPtrSet(&paParms[0], szName, strlen(szName) + 1);
     570        if (delProperties[i].isHost)
     571            callHandle.rc = pTable->pfnHostCall(pTable->pvService, command,
     572                                                1, paParms);
     573        else
     574            pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL, command,
     575                            1, paParms);
     576        if (delProperties[i].isAllowed && RT_FAILURE(callHandle.rc))
     577        {
     578            RTPrintf("Deleting property '%s' failed with rc=%Rrc.\n",
     579                     delProperties[i].pcszName, callHandle.rc);
     580            rc = callHandle.rc;
     581        }
     582        else if (   !delProperties[i].isAllowed
     583                 && (callHandle.rc != VERR_PERMISSION_DENIED)
     584                )
     585        {
     586            RTPrintf("Deleting property '%s' returned %Rrc instead of VERR_PERMISSION_DENIED.\n",
     587                     delProperties[i].pcszName, callHandle.rc);
     588            rc = VERR_UNRESOLVED_ERROR;
     589        }
     590    }
     591    return rc;
     592}
     593
     594/** Array of properties for testing GET_PROP_HOST. */
     595static const struct
     596{
     597    /** Property name */
     598    const char *pcszName;
     599    /** What value/flags pattern do we expect back? */
     600    const char *pcchValue;
     601    /** What size should the value/flags array be? */
     602    uint32_t cchValue;
     603    /** Should this proeprty exist? */
     604    bool exists;
     605    /** Do we expect a particular timestamp? */
     606    bool hasTimestamp;
     607    /** What timestamp if any do ex expect? */
     608    uint64_t u64Timestamp;
     609}
     610getProperties[] =
     611{
     612    { "test/name/", "test/value/\0", sizeof("test/value/\0"), true, true, 0 },
     613    { "test name", "test value\0TRANSIENT, READONLY",
     614      sizeof("test value\0TRANSIENT, READONLY"), true, true, 999 },
     615    { "TEST NAME", "TEST VALUE\0RDONLYHOST", sizeof("TEST VALUE\0RDONLYHOST"),
     616      true, true, 999999 },
     617    { "/test/name", "/test/value\0RDONLYGUEST",
     618      sizeof("/test/value\0RDONLYGUEST"), true, true, 999999999999 },
     619    { "Green", "Go!\0READONLY", sizeof("Go!\0READONLY"), true, false, 0 },
     620    { "Blue", "What on earth...?\0", sizeof("What on earth...?\0"), true,
     621      false, 0 },
     622    { "Red", "", 0, false, false, 0 },
     623    { NULL, NULL, 0, false, false, 0 }
     624};
     625
     626/**
     627 * Test the GET_PROP_HOST function.
     628 * @returns iprt status value to indicate whether the test went as expected.
     629 * @note    prints its own diagnostic information to stdout.
     630 */
     631int testGetProp(VBOXHGCMSVCFNTABLE *pTable)
     632{
     633    int rc = VINF_SUCCESS, rc2 = VINF_SUCCESS;
     634    RTPrintf("Testing the GET_PROP_HOST call.\n");
     635    for (unsigned i = 0; RT_SUCCESS(rc) && (getProperties[i].pcszName != NULL);
     636         ++i)
     637    {
     638        VBOXHGCMSVCPARM paParms[4];
     639        /* Work around silly constant issues - we ought to allow passing
     640         * constant strings in the hgcm parameters. */
     641        char szName[MAX_NAME_LEN] = "";
     642        char szBuffer[MAX_VALUE_LEN + MAX_FLAGS_LEN];
     643        AssertBreakStmt(sizeof(szBuffer) >= getProperties[i].cchValue,
     644                        rc = VERR_INTERNAL_ERROR);
     645        strncat(szName, getProperties[i].pcszName, sizeof(szName));
     646        VBoxHGCMParmPtrSet(&paParms[0], szName, strlen(szName) + 1);
     647        VBoxHGCMParmPtrSet(&paParms[1], szBuffer, sizeof(szBuffer));
     648        rc2 = pTable->pfnHostCall(pTable->pvService, GET_PROP_HOST, 4,
     649                                  paParms);
     650        if (getProperties[i].exists && RT_FAILURE(rc2))
     651        {
     652            RTPrintf("Getting property '%s' failed with rc=%Rrc.\n",
     653                     getProperties[i].pcszName, rc2);
     654            rc = rc2;
     655        }
     656        else if (!getProperties[i].exists && (rc2 != VERR_NOT_FOUND))
     657        {
     658            RTPrintf("Getting property '%s' returned %Rrc instead of VERR_NOT_FOUND.\n",
     659                     getProperties[i].pcszName, rc2);
     660            rc = VERR_UNRESOLVED_ERROR;
     661        }
     662        if (RT_SUCCESS(rc) && getProperties[i].exists)
     663        {
     664            uint32_t u32ValueLen;
     665            rc = VBoxHGCMParmUInt32Get(&paParms[3], &u32ValueLen);
     666            if (RT_FAILURE(rc))
     667                RTPrintf("Failed to get the size of the output buffer for property '%s'\n",
     668                         getProperties[i].pcszName);
     669            if (   RT_SUCCESS(rc)
     670                && (memcmp(szBuffer, getProperties[i].pcchValue,
     671                           getProperties[i].cchValue) != 0)
     672               )
     673            {
     674                RTPrintf("Unexpected result '%.*s' for property '%s', expected '%.*s'.\n",
     675                         u32ValueLen, szBuffer, getProperties[i].pcszName,
     676                         getProperties[i].cchValue, getProperties[i].pcchValue);
     677                rc = VERR_UNRESOLVED_ERROR;
     678            }
     679            if (RT_SUCCESS(rc) && getProperties[i].hasTimestamp)
     680            {
     681                uint64_t u64Timestamp;
     682                rc = VBoxHGCMParmUInt64Get(&paParms[2], &u64Timestamp);
     683                if (RT_FAILURE(rc))
     684                    RTPrintf("Failed to get the timestamp for property '%s'\n",
     685                             getProperties[i].pcszName);
     686                if (   RT_SUCCESS(rc)
     687                    && (u64Timestamp != getProperties[i].u64Timestamp)
     688                   )
     689                {
     690                    RTPrintf("Bad timestamp %llu for property '%s', expected %llu.\n",
     691                             u64Timestamp, getProperties[i].pcszName,
     692                             getProperties[i].u64Timestamp);
     693                    rc = VERR_UNRESOLVED_ERROR;
     694                }
     695            }
     696        }
     697    }
     698    return rc;
     699}
     700
    86701int main(int argc, char **argv)
    87702{
     703    VBOXHGCMSVCFNTABLE svcTable;
     704    VBOXHGCMSVCHELPERS svcHelpers;
     705    initTable(&svcTable, &svcHelpers);
    88706    RTR3Init();
    89707    if (RT_FAILURE(testConvertFlags()))
    90708        return 1;
     709    /* The function is inside the service, not HGCM. */
     710    if (RT_FAILURE(VBoxHGCMSvcLoad(&svcTable)))
     711    {
     712        RTPrintf("Failed to start HGCM service.\n");
     713        return 1;
     714    }
     715    if (RT_FAILURE(testSetPropsHost(&svcTable)))
     716        return 1;
     717    if (RT_FAILURE(testEnumPropsHost(&svcTable)))
     718        return 1;
     719    if (RT_FAILURE(testSetProp(&svcTable)))
     720        return 1;
     721    if (RT_FAILURE(testDelProp(&svcTable)))
     722        return 1;
     723    if (RT_FAILURE(testGetProp(&svcTable)))
     724        return 1;
    91725    RTPrintf("tstGuestPropSvc: SUCCEEDED.\n");
    92726    return 0;
    93727}
    94 
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