VirtualBox

Ignore:
Timestamp:
Nov 3, 2008 4:39:22 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
38738
Message:

Backed out 38734

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp

    r13759 r13763  
    22/** @file
    33 *
    4  * Testcase for the guest property service.
     4 * Testcase for the guest property service.  For now, this only tests
     5 * flag conversion.
    56 */
    67
     
    3031using namespace guestProp;
    3132
    32 extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable);
    33 
    34 /** Set a pointer value to an HGCM parameter structure */
    35 static 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 */
    43 static 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 */
    55 static 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 */
    67 struct VBOXHGCMCALLHANDLE_TYPEDEF
    68 {
    69     /** Where to store the result code */
    70     int32_t rc;
    71 };
    72 
    73 /** Call completion callback for guest calls. */
    74 static void callComplete(VBOXHGCMCALLHANDLE callHandle, int32_t rc)
    75 {
    76     callHandle->rc = rc;
    77 }
    78 
    7933/**
    80  * Initialise the HGCM service table as much as we need to start the
    81  * service
    82  * @param  pTable the table to initialise
    83  */
    84 void 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.
     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.
    9636 */
    9737struct flagStrings
     
    10444validFlagStrings[] =
    10545{
    106     { "  ", "" },
     46    { "", "" },
    10747    { "transient, ", "TRANSIENT" },
    108     { "  rdOnLyHOST, transIENT  ,     READONLY    ", "TRANSIENT, READONLY" },
    109     { " rdonlyguest", "RDONLYGUEST" },
    110     { "rdonlyhost     ", "RDONLYHOST" }
     48    { "  rdOnLyHOST, transIENT  ,     READONLY    ", "TRANSIENT, READONLY" }
    11149};
    11250
    113 /**
    114  * A list of invalid flag strings for testConvertFlags.  The flag conversion
    115  * functions should reject these.
    116  */
    117 const 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  */
    12851int testConvertFlags()
    12952{
     
    13255    for (unsigned i = 0; i < RT_ELEMENTS(validFlagStrings) && RT_SUCCESS(rc); ++i)
    13356    {
    134         char szFlagBuffer[MAX_FLAGS_LEN * 2];
     57        char szFlagBuffer[MAX_FLAGS_LEN];
    13558        uint32_t fFlags;
    13659        rc = validateFlags(validFlagStrings[i].pcszIn, &fFlags);
    13760        if (RT_FAILURE(rc))
    138             RTPrintf("tstGuestPropSvc: FAILURE - Failed to validate flag string '%s'.\n", validFlagStrings[i].pcszIn);
     61            RTPrintf("tstGuestPropSvc: FAILURE - Failed to validate flag string %s.\n", validFlagStrings[i].pcszIn);
    13962        if (RT_SUCCESS(rc))
    14063        {
    14164            rc = writeFlags(fFlags, szFlagBuffer);
    14265            if (RT_FAILURE(rc))
    143                 RTPrintf("tstGuestPropSvc: FAILURE - Failed to convert flag string '%s' back to a string.\n",
     66                RTPrintf("tstGuestPropSvc: FAILURE - Failed to convert flag string %s back to a string.\n",
    14467                            validFlagStrings[i].pcszIn);
    14568        }
    14669        if (RT_SUCCESS(rc) && (strlen(szFlagBuffer) > MAX_FLAGS_LEN - 1))
    14770        {
    148             RTPrintf("tstGuestPropSvc: FAILURE - String '%s' converts back to a flag string which is too long.\n",
     71            RTPrintf("tstGuestPropSvc: FAILURE - String %s converts back to a flag string which is too long.\n",
    14972                        validFlagStrings[i].pcszIn);
    15073            rc = VERR_TOO_MUCH_DATA;
     
    15275        if (RT_SUCCESS(rc) && (strcmp(szFlagBuffer, validFlagStrings[i].pcszOut) != 0))
    15376        {
    154             RTPrintf("tstGuestPropSvc: FAILURE - String '%s' converts back to '%s' instead of to '%s'\n",
     77            RTPrintf("tstGuestPropSvc: FAILURE - String %s converts back to %s instead of to %s\n",
    15578                        validFlagStrings[i].pcszIn, szFlagBuffer,
    15679                        validFlagStrings[i].pcszOut);
    15780            rc = VERR_PARSE_ERROR;
    158         }
    159     }
    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     }
    188     return rc;
    189 }
    190 
    191 /**
    192  * List of property names for testSetPropsHost.
    193  */
    194 const 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  */
    206 const 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  */
    218 uint64_t au64TimestampBlock[] =
    219 {
    220     0, 999, 999999, 999999999999, 0
    221 };
    222 
    223 /**
    224  * List of property flags for testSetPropsHost.
    225  */
    226 const 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  */
    240 int 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 */
    265 static 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 */
    275 static 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  */
    288 static const size_t cchEnumBuffer0 =
    289 sizeof("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 */
    295 static 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 */
    303 static 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  */
    314 static const size_t cchEnumBuffer1 =
    315 sizeof("TEST NAME\0TEST VALUE\0""999999\0RDONLYHOST\0"
    316 "/test/name\0/test/value\0""999999999999\0RDONLYGUEST\0\0\0\0\0") - 1;
    317 
    318 static 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 }
    331 enumStrings[] =
    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  */
    358 int 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. */
    436 static 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 }
    451 setProperties[] =
    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  */
    470 int 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. */
    526 static 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 }
    535 delProperties[] =
    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  */
    553 int 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. */
    595 static 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 }
    610 getProperties[] =
    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  */
    631 int 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             }
    69681        }
    69782    }
     
    70186int main(int argc, char **argv)
    70287{
    703     VBOXHGCMSVCFNTABLE svcTable;
    704     VBOXHGCMSVCHELPERS svcHelpers;
    705     initTable(&svcTable, &svcHelpers);
    70688    RTR3Init();
    70789    if (RT_FAILURE(testConvertFlags()))
    708         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)))
    72490        return 1;
    72591    RTPrintf("tstGuestPropSvc: SUCCEEDED.\n");
    72692    return 0;
    72793}
     94
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