Changeset 13779 in vbox for trunk/src/VBox/HostServices/GuestProperties/testcase
- Timestamp:
- Nov 4, 2008 9:46:13 AM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 38763
- Location:
- trunk/src/VBox/HostServices/GuestProperties/testcase
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/GuestProperties/testcase/Makefile.kmk
r13763 r13779 29 29 PROGRAMS += tstGuestPropSvc 30 30 tstGuestPropSvc_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. 33 tstGuestPropSvc_DEFS = VBOX_WITH_HGCM VBOX_GUEST_PROP_TEST_NOTHREAD 34 tstGuestPropSvc_SOURCES = tstGuestPropSvc.cpp ../service.cpp 33 35 tstGuestPropSvc_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. 39 ifdef 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 47 endif 34 48 35 49 endif # VBOX_WITH_TESTCASES -
trunk/src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp
r13763 r13779 2 2 /** @file 3 3 * 4 * Testcase for the guest property service. For now, this only tests 5 * flag conversion. 4 * Testcase for the guest property service. 6 5 */ 7 6 … … 31 30 using namespace guestProp; 32 31 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. 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 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 */ 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. 36 96 */ 37 97 struct flagStrings … … 44 104 validFlagStrings[] = 45 105 { 46 { " ", "" },106 { " ", "" }, 47 107 { "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 */ 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 */ 51 128 int testConvertFlags() 52 129 { … … 55 132 for (unsigned i = 0; i < RT_ELEMENTS(validFlagStrings) && RT_SUCCESS(rc); ++i) 56 133 { 57 char szFlagBuffer[MAX_FLAGS_LEN ];134 char szFlagBuffer[MAX_FLAGS_LEN * 2]; 58 135 uint32_t fFlags; 59 136 rc = validateFlags(validFlagStrings[i].pcszIn, &fFlags); 60 137 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); 62 139 if (RT_SUCCESS(rc)) 63 140 { 64 141 rc = writeFlags(fFlags, szFlagBuffer); 65 142 if (RT_FAILURE(rc)) 66 RTPrintf("tstGuestPropSvc: FAILURE - Failed to convert flag string %sback to a string.\n",143 RTPrintf("tstGuestPropSvc: FAILURE - Failed to convert flag string '%s' back to a string.\n", 67 144 validFlagStrings[i].pcszIn); 68 145 } 69 146 if (RT_SUCCESS(rc) && (strlen(szFlagBuffer) > MAX_FLAGS_LEN - 1)) 70 147 { 71 RTPrintf("tstGuestPropSvc: FAILURE - String %sconverts 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", 72 149 validFlagStrings[i].pcszIn); 73 150 rc = VERR_TOO_MUCH_DATA; … … 75 152 if (RT_SUCCESS(rc) && (strcmp(szFlagBuffer, validFlagStrings[i].pcszOut) != 0)) 76 153 { 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", 78 155 validFlagStrings[i].pcszIn, szFlagBuffer, 79 156 validFlagStrings[i].pcszOut); … … 81 158 } 82 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 } 83 188 return rc; 84 189 } 85 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 } 696 } 697 } 698 return rc; 699 } 700 86 701 int main(int argc, char **argv) 87 702 { 703 VBOXHGCMSVCFNTABLE svcTable; 704 VBOXHGCMSVCHELPERS svcHelpers; 705 initTable(&svcTable, &svcHelpers); 88 706 RTR3Init(); 89 707 if (RT_FAILURE(testConvertFlags())) 90 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))) 724 return 1; 91 725 RTPrintf("tstGuestPropSvc: SUCCEEDED.\n"); 92 726 return 0; 93 727 } 94
Note:
See TracChangeset
for help on using the changeset viewer.