Changeset 39228 in vbox for trunk/src/VBox/HostServices/GuestProperties/testcase
- Timestamp:
- Nov 8, 2011 11:06:20 AM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 74754
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp
r36412 r39228 21 21 *******************************************************************************/ 22 22 #include <VBox/HostServices/GuestPropertySvc.h> 23 #include <iprt/initterm.h>24 #include <iprt/stream.h>25 23 #include <iprt/test.h> 24 #include <iprt/time.h> 25 26 26 27 27 /******************************************************************************* … … 54 54 void initTable(VBOXHGCMSVCFNTABLE *pTable, VBOXHGCMSVCHELPERS *pHelpers) 55 55 { 56 pTable->cbSize = sizeof (VBOXHGCMSVCFNTABLE);57 pTable->u32Version = VBOX_HGCM_SVC_VERSION;58 pHelpers->pfnCallComplete = callComplete;59 pTable->pHelpers = pHelpers;56 pTable->cbSize = sizeof (VBOXHGCMSVCFNTABLE); 57 pTable->u32Version = VBOX_HGCM_SVC_VERSION; 58 pHelpers->pfnCallComplete = callComplete; 59 pTable->pHelpers = pHelpers; 60 60 } 61 61 … … 72 72 const char *pcszOut; 73 73 } 74 g_ validFlagStrings[] =74 g_aValidFlagStrings[] = 75 75 { 76 76 /* pcszIn, pcszOut */ … … 91 91 * functions should reject these. 92 92 */ 93 const char *g_ invalidFlagStrings[] =93 const char *g_apszInvalidFlagStrings[] = 94 94 { 95 95 "RDONLYHOST,,", … … 102 102 * @note prints its own diagnostic information to stdout. 103 103 */ 104 int testConvertFlags()104 static void testConvertFlags(void) 105 105 { 106 106 int rc = VINF_SUCCESS; 107 107 char *pszFlagBuffer = (char *)RTTestGuardedAllocTail(g_hTest, MAX_FLAGS_LEN); 108 108 109 RT Printf("tstGuestPropSvc: Testing conversion of valid flags strings.\n");110 for (unsigned i = 0; i < RT_ELEMENTS(g_ validFlagStrings) && RT_SUCCESS(rc); ++i)109 RTTestISub("Conversion of valid flags strings"); 110 for (unsigned i = 0; i < RT_ELEMENTS(g_aValidFlagStrings) && RT_SUCCESS(rc); ++i) 111 111 { 112 112 uint32_t fFlags; 113 rc = validateFlags(g_ validFlagStrings[i].pcszIn, &fFlags);113 rc = validateFlags(g_aValidFlagStrings[i].pcszIn, &fFlags); 114 114 if (RT_FAILURE(rc)) 115 RT Printf("tstGuestPropSvc: FAILURE - Failed to validate flag string '%s'.\n", g_validFlagStrings[i].pcszIn);115 RTTestIFailed("Failed to validate flag string '%s'", g_aValidFlagStrings[i].pcszIn); 116 116 if (RT_SUCCESS(rc)) 117 117 { 118 118 rc = writeFlags(fFlags, pszFlagBuffer); 119 119 if (RT_FAILURE(rc)) 120 RT Printf("tstGuestPropSvc: FAILURE - Failed to convert flag string '%s' back to a string.\n",121 g_validFlagStrings[i].pcszIn);120 RTTestIFailed("Failed to convert flag string '%s' back to a string.", 121 g_aValidFlagStrings[i].pcszIn); 122 122 } 123 123 if (RT_SUCCESS(rc) && (strlen(pszFlagBuffer) > MAX_FLAGS_LEN - 1)) 124 124 { 125 RT Printf("tstGuestPropSvc: FAILURE -String '%s' converts back to a flag string which is too long.\n",126 g_validFlagStrings[i].pcszIn);125 RTTestIFailed("String '%s' converts back to a flag string which is too long.\n", 126 g_aValidFlagStrings[i].pcszIn); 127 127 rc = VERR_TOO_MUCH_DATA; 128 128 } 129 if (RT_SUCCESS(rc) && (strcmp(pszFlagBuffer, g_ validFlagStrings[i].pcszOut) != 0))130 { 131 RT Printf("tstGuestPropSvc: FAILURE -String '%s' converts back to '%s' instead of to '%s'\n",132 g_validFlagStrings[i].pcszIn, pszFlagBuffer,133 g_validFlagStrings[i].pcszOut);129 if (RT_SUCCESS(rc) && (strcmp(pszFlagBuffer, g_aValidFlagStrings[i].pcszOut) != 0)) 130 { 131 RTTestIFailed("String '%s' converts back to '%s' instead of to '%s'\n", 132 g_aValidFlagStrings[i].pcszIn, pszFlagBuffer, 133 g_aValidFlagStrings[i].pcszOut); 134 134 rc = VERR_PARSE_ERROR; 135 135 } … … 137 137 if (RT_SUCCESS(rc)) 138 138 { 139 RT Printf("Testing rejection of invalid flags strings.\n");140 for (unsigned i = 0; i < RT_ELEMENTS(g_ invalidFlagStrings) && RT_SUCCESS(rc); ++i)139 RTTestISub("Rejection of invalid flags strings"); 140 for (unsigned i = 0; i < RT_ELEMENTS(g_apszInvalidFlagStrings) && RT_SUCCESS(rc); ++i) 141 141 { 142 142 uint32_t fFlags; 143 143 /* This is required to fail. */ 144 if (RT_SUCCESS(validateFlags(g_ invalidFlagStrings[i], &fFlags)))144 if (RT_SUCCESS(validateFlags(g_apszInvalidFlagStrings[i], &fFlags))) 145 145 { 146 RT Printf("String '%s' was incorrectly accepted as a valid flag string.\n",147 g_invalidFlagStrings[i]);146 RTTestIFailed("String '%s' was incorrectly accepted as a valid flag string.\n", 147 g_apszInvalidFlagStrings[i]); 148 148 rc = VERR_PARSE_ERROR; 149 149 } … … 153 153 { 154 154 uint32_t u32BadFlags = ALLFLAGS << 1; 155 RT Printf("Testing rejection of an invalid flags field.\n");155 RTTestISub("Rejection of an invalid flags field"); 156 156 /* This is required to fail. */ 157 157 if (RT_SUCCESS(writeFlags(u32BadFlags, pszFlagBuffer))) 158 158 { 159 RT Printf("Flags 0x%x were incorrectly written out as '%.*s'\n",160 u32BadFlags, MAX_FLAGS_LEN, pszFlagBuffer);159 RTTestIFailed("Flags 0x%x were incorrectly written out as '%.*s'\n", 160 u32BadFlags, MAX_FLAGS_LEN, pszFlagBuffer); 161 161 rc = VERR_PARSE_ERROR; 162 162 } … … 164 164 165 165 RTTestGuardedFree(g_hTest, pszFlagBuffer); 166 return rc;167 166 } 168 167 … … 170 169 * List of property names for testSetPropsHost. 171 170 */ 172 const char * apcszNameBlock[] =171 const char *g_apcszNameBlock[] = 173 172 { 174 173 "test/name/", … … 182 181 * List of property values for testSetPropsHost. 183 182 */ 184 const char * apcszValueBlock[] =183 const char *g_apcszValueBlock[] = 185 184 { 186 185 "test/value/", … … 194 193 * List of property timestamps for testSetPropsHost. 195 194 */ 196 uint64_t au64TimestampBlock[] =195 uint64_t g_au64TimestampBlock[] = 197 196 { 198 197 0, 999, 999999, UINT64_C(999999999999), 0 … … 202 201 * List of property flags for testSetPropsHost. 203 202 */ 204 const char * apcszFlagsBlock[] =203 const char *g_apcszFlagsBlock[] = 205 204 { 206 205 "", … … 216 215 * @note prints its own diagnostic information to stdout. 217 216 */ 218 int testSetPropsHost(VBOXHGCMSVCFNTABLE *ptable) 219 { 220 int rc = VINF_SUCCESS; 221 RTPrintf("Testing the SET_PROPS_HOST call.\n"); 222 if (!VALID_PTR(ptable->pfnHostCall)) 223 { 224 RTPrintf("Invalid pfnHostCall() pointer\n"); 225 rc = VERR_INVALID_POINTER; 226 } 227 if (RT_SUCCESS(rc)) 228 { 229 VBOXHGCMSVCPARM paParms[4]; 230 paParms[0].setPointer ((void *) apcszNameBlock, 0); 231 paParms[1].setPointer ((void *) apcszValueBlock, 0); 232 paParms[2].setPointer ((void *) au64TimestampBlock, 0); 233 paParms[3].setPointer ((void *) apcszFlagsBlock, 0); 234 rc = ptable->pfnHostCall(ptable->pvService, SET_PROPS_HOST, 4, 235 paParms); 236 if (RT_FAILURE(rc)) 237 RTPrintf("SET_PROPS_HOST call failed with rc=%Rrc\n", rc); 238 } 239 return rc; 217 static void testSetPropsHost(VBOXHGCMSVCFNTABLE *ptable) 218 { 219 RTTestISub("SET_PROPS_HOST"); 220 RTTESTI_CHECK_RETV(RT_VALID_PTR(ptable->pfnHostCall)); 221 222 VBOXHGCMSVCPARM aParms[4]; 223 aParms[0].setPointer((void *)g_apcszNameBlock, 0); 224 aParms[1].setPointer((void *)g_apcszValueBlock, 0); 225 aParms[2].setPointer((void *)g_au64TimestampBlock, 0); 226 aParms[3].setPointer((void *)g_apcszFlagsBlock, 0); 227 RTTESTI_CHECK_RC(ptable->pfnHostCall(ptable->pvService, SET_PROPS_HOST, 4, &aParms[0]), VINF_SUCCESS); 240 228 } 241 229 242 230 /** Result strings for zeroth enumeration test */ 243 static const char * pcchEnumResult0[] =231 static const char *g_apchEnumResult0[] = 244 232 { 245 233 "test/name/\0test/value/\0""0\0", … … 251 239 252 240 /** Result string sizes for zeroth enumeration test */ 253 static const uint32_t cchEnumResult0[] =241 static const uint32_t g_acbEnumResult0[] = 254 242 { 255 243 sizeof("test/name/\0test/value/\0""0\0"), … … 264 252 * the - 1 at the end is because of the hidden zero terminator 265 253 */ 266 static const uint32_t cchEnumBuffer0 =267 sizeof("test/name/\0test/value/\0""0\0\0"268 "test name\0test value\0""999\0TRANSIENT, READONLY\0"269 "TEST NAME\0TEST VALUE\0""999999\0RDONLYHOST\0"270 "/test/name\0/test/value\0""999999999999\0RDONLYGUEST\0\0\0\0\0") - 1;254 static const uint32_t g_cbEnumBuffer0 = 255 sizeof("test/name/\0test/value/\0""0\0\0" 256 "test name\0test value\0""999\0TRANSIENT, READONLY\0" 257 "TEST NAME\0TEST VALUE\0""999999\0RDONLYHOST\0" 258 "/test/name\0/test/value\0""999999999999\0RDONLYGUEST\0\0\0\0\0") - 1; 271 259 272 260 /** Result strings for first and second enumeration test */ 273 static const char * pcchEnumResult1[] =261 static const char *g_apchEnumResult1[] = 274 262 { 275 263 "TEST NAME\0TEST VALUE\0""999999\0RDONLYHOST", … … 279 267 280 268 /** Result string sizes for first and second enumeration test */ 281 static const uint32_t cchEnumResult1[] =269 static const uint32_t g_acbEnumResult1[] = 282 270 { 283 271 sizeof("TEST NAME\0TEST VALUE\0""999999\0RDONLYHOST"), … … 290 278 * the - 1 at the end is because of the hidden zero terminator 291 279 */ 292 static const uint32_t cchEnumBuffer1 =293 sizeof("TEST NAME\0TEST VALUE\0""999999\0RDONLYHOST\0"294 "/test/name\0/test/value\0""999999999999\0RDONLYGUEST\0\0\0\0\0") - 1;280 static const uint32_t g_cbEnumBuffer1 = 281 sizeof("TEST NAME\0TEST VALUE\0""999999\0RDONLYHOST\0" 282 "/test/name\0/test/value\0""999999999999\0RDONLYGUEST\0\0\0\0\0") - 1; 295 283 296 284 static const struct enumStringStruct 297 285 { 298 286 /** The enumeration pattern to test */ 299 const char *pcszPatterns;287 const char *pszPatterns; 300 288 /** The size of the pattern string */ 301 const uint32_t cchPatterns;289 const uint32_t cchPatterns; 302 290 /** The expected enumeration output strings */ 303 const char **ppcchResult;291 const char **papchResult; 304 292 /** The size of the output strings */ 305 const uint32_t *p cchResult;293 const uint32_t *pacchResult; 306 294 /** The size of the buffer needed for the enumeration */ 307 const uint32_t cchBuffer; 308 } 309 enumStrings[] = 295 const uint32_t cbBuffer; 296 } g_aEnumStrings[] = 310 297 { 311 298 { 312 299 "", sizeof(""), 313 pcchEnumResult0,314 cchEnumResult0,315 cchEnumBuffer0300 g_apchEnumResult0, 301 g_acbEnumResult0, 302 g_cbEnumBuffer0 316 303 }, 317 304 { 318 305 "/*\0?E*", sizeof("/*\0?E*"), 319 pcchEnumResult1,320 cchEnumResult1,321 cchEnumBuffer1306 g_apchEnumResult1, 307 g_acbEnumResult1, 308 g_cbEnumBuffer1 322 309 }, 323 310 { 324 311 "/*|?E*", sizeof("/*|?E*"), 325 pcchEnumResult1,326 cchEnumResult1,327 cchEnumBuffer1312 g_apchEnumResult1, 313 g_acbEnumResult1, 314 g_cbEnumBuffer1 328 315 } 329 316 }; … … 334 321 * @note prints its own diagnostic information to stdout. 335 322 */ 336 int testEnumPropsHost(VBOXHGCMSVCFNTABLE *ptable) 337 { 338 int rc = VINF_SUCCESS; 339 RTPrintf("Testing the ENUM_PROPS_HOST call.\n"); 340 if (!VALID_PTR(ptable->pfnHostCall)) 341 { 342 RTPrintf("Invalid pfnHostCall() pointer\n"); 343 rc = VERR_INVALID_POINTER; 344 } 345 for (unsigned i = 0; RT_SUCCESS(rc) && i < RT_ELEMENTS(enumStrings); 346 ++i) 347 { 348 char buffer[2048]; 349 VBOXHGCMSVCPARM paParms[3]; 350 paParms[0].setPointer ((void *) enumStrings[i].pcszPatterns, 351 enumStrings[i].cchPatterns); 352 paParms[1].setPointer ((void *) buffer, 353 enumStrings[i].cchBuffer - 1); 354 AssertBreakStmt(sizeof(buffer) > enumStrings[i].cchBuffer, 355 rc = VERR_INTERNAL_ERROR); 356 if (RT_SUCCESS(rc)) 357 { 358 /* This should fail as the buffer is too small. */ 359 int rc2 = ptable->pfnHostCall(ptable->pvService, ENUM_PROPS_HOST, 360 3, paParms); 361 if (rc2 != VERR_BUFFER_OVERFLOW) 323 static void testEnumPropsHost(VBOXHGCMSVCFNTABLE *ptable) 324 { 325 RTTestISub("ENUM_PROPS_HOST"); 326 RTTESTI_CHECK_RETV(RT_VALID_PTR(ptable->pfnHostCall)); 327 328 for (unsigned i = 0; i < RT_ELEMENTS(g_aEnumStrings); ++i) 329 { 330 VBOXHGCMSVCPARM aParms[3]; 331 char abBuffer[2048]; 332 RTTESTI_CHECK_RETV(g_aEnumStrings[i].cbBuffer < sizeof(abBuffer)); 333 334 /* Check that we get buffer overflow with a too small buffer. */ 335 aParms[0].setPointer((void *)g_aEnumStrings[i].pszPatterns, g_aEnumStrings[i].cchPatterns); 336 aParms[1].setPointer((void *)abBuffer, g_aEnumStrings[i].cbBuffer - 1); 337 int rc2 = ptable->pfnHostCall(ptable->pvService, ENUM_PROPS_HOST, 3, aParms); 338 if (rc2 == VERR_BUFFER_OVERFLOW) 339 { 340 uint32_t cbNeeded; 341 RTTESTI_CHECK_RC(rc2 = aParms[2].getUInt32(&cbNeeded), VINF_SUCCESS); 342 if (RT_SUCCESS(rc2)) 343 RTTESTI_CHECK_MSG(cbNeeded == g_aEnumStrings[i].cbBuffer, 344 ("expected %u, got %u, pattern %d\n", g_aEnumStrings[i].cbBuffer, cbNeeded, i)); 345 } 346 else 347 RTTestIFailed("ENUM_PROPS_HOST returned %Rrc instead of VERR_BUFFER_OVERFLOW on too small buffer, pattern number %d.", rc2, i); 348 349 /* Make a successfull call. */ 350 aParms[0].setPointer((void *)g_aEnumStrings[i].pszPatterns, g_aEnumStrings[i].cchPatterns); 351 aParms[1].setPointer((void *)abBuffer, g_aEnumStrings[i].cbBuffer); 352 rc2 = ptable->pfnHostCall(ptable->pvService, ENUM_PROPS_HOST, 3, aParms); 353 if (rc2 == VINF_SUCCESS) 354 { 355 /* Look for each of the result strings in the buffer which was returned */ 356 for (unsigned j = 0; g_aEnumStrings[i].papchResult[j] != NULL; ++j) 362 357 { 363 RTPrintf("ENUM_PROPS_HOST returned %Rrc instead of VERR_BUFFER_OVERFLOW on too small buffer, pattern number %d\n", rc2, i); 364 rc = VERR_BUFFER_OVERFLOW; 358 bool found = false; 359 for (unsigned k = 0; !found && k < g_aEnumStrings[i].cbBuffer 360 - g_aEnumStrings[i].pacchResult[j]; 361 ++k) 362 if (memcmp(abBuffer + k, g_aEnumStrings[i].papchResult[j], 363 g_aEnumStrings[i].pacchResult[j]) == 0) 364 found = true; 365 if (!found) 366 RTTestIFailed("ENUM_PROPS_HOST did not produce the expected output for pattern %d.", i); 365 367 } 366 else 367 { 368 uint32_t cchBufferActual; 369 rc = paParms[2].getUInt32 (&cchBufferActual); 370 if (RT_SUCCESS(rc) && cchBufferActual != enumStrings[i].cchBuffer) 371 { 372 RTPrintf("ENUM_PROPS_HOST requested a buffer size of %lu instead of %lu for pattern number %d\n", cchBufferActual, enumStrings[i].cchBuffer, i); 373 rc = VERR_OUT_OF_RANGE; 374 } 375 else if (RT_FAILURE(rc)) 376 RTPrintf("ENUM_PROPS_HOST did not return the required buffer size properly for pattern %d\n", i); 377 } 378 } 379 if (RT_SUCCESS(rc)) 380 { 381 paParms[1].setPointer ((void *) buffer, enumStrings[i].cchBuffer); 382 rc = ptable->pfnHostCall(ptable->pvService, ENUM_PROPS_HOST, 383 3, paParms); 384 if (RT_FAILURE(rc)) 385 RTPrintf("ENUM_PROPS_HOST call failed for pattern %d with rc=%Rrc\n", i, rc); 386 else 387 /* Look for each of the result strings in the buffer which was returned */ 388 for (unsigned j = 0; RT_SUCCESS(rc) && enumStrings[i].ppcchResult[j] != NULL; 389 ++j) 390 { 391 bool found = false; 392 for (unsigned k = 0; !found && k < enumStrings[i].cchBuffer 393 - enumStrings[i].pcchResult[j]; 394 ++k) 395 if (memcmp(buffer + k, enumStrings[i].ppcchResult[j], 396 enumStrings[i].pcchResult[j]) == 0) 397 found = true; 398 if (!found) 399 { 400 RTPrintf("ENUM_PROPS_HOST did not produce the expected output for pattern %d\n", 401 i); 402 rc = VERR_UNRESOLVED_ERROR; 403 } 404 } 405 } 406 } 407 return rc; 368 } 369 else 370 RTTestIFailed("ENUM_PROPS_HOST returned %Rrc instead of VINF_SUCCESS, pattern number %d.", rc2, i); 371 } 408 372 } 409 373 … … 437 401 else if (useSetProp) 438 402 command = SET_PROP; 439 VBOXHGCMSVCPARM paParms[3];403 VBOXHGCMSVCPARM aParms[3]; 440 404 /* Work around silly constant issues - we ought to allow passing 441 405 * constant strings in the hgcm parameters. */ … … 446 410 RTStrPrintf(szValue, sizeof(szValue), "%s", pcszValue); 447 411 RTStrPrintf(szFlags, sizeof(szFlags), "%s", pcszFlags); 448 paParms[0].setPointer (szName, (uint32_t)strlen(szName) + 1);449 paParms[1].setPointer (szValue, (uint32_t)strlen(szValue) + 1);450 paParms[2].setPointer (szFlags, (uint32_t)strlen(szFlags) + 1);412 aParms[0].setPointer (szName, (uint32_t)strlen(szName) + 1); 413 aParms[1].setPointer (szValue, (uint32_t)strlen(szValue) + 1); 414 aParms[2].setPointer (szFlags, (uint32_t)strlen(szFlags) + 1); 451 415 if (isHost) 452 416 callHandle.rc = pTable->pfnHostCall(pTable->pvService, command, 453 useSetProp ? 3 : 2, paParms);417 useSetProp ? 3 : 2, aParms); 454 418 else 455 419 pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL, command, 456 useSetProp ? 3 : 2, paParms);420 useSetProp ? 3 : 2, aParms); 457 421 return callHandle.rc; 458 422 } 459 460 461 /** Array of properties for testing SET_PROP_HOST and _GUEST. */462 static const struct463 {464 /** Property name */465 const char *pcszName;466 /** Property value */467 const char *pcszValue;468 /** Property flags */469 const char *pcszFlags;470 /** Should this be set as the host or the guest? */471 bool isHost;472 /** Should we use SET_PROP or SET_PROP_VALUE? */473 bool useSetProp;474 /** Should this succeed or be rejected with VERR_PERMISSION_DENIED? */475 bool isAllowed;476 }477 setProperties[] =478 {479 { "Red", "Stop!", "transient", false, true, true },480 { "Amber", "Caution!", "", false, false, true },481 { "Green", "Go!", "readonly", true, true, true },482 { "Blue", "What on earth...?", "", true, false, true },483 { "/test/name", "test", "", false, true, false },484 { "TEST NAME", "test", "", true, true, false },485 { "Green", "gone out...", "", false, false, false },486 { "Green", "gone out...", "", true, false, false },487 { NULL, NULL, NULL, false, false, false }488 };489 423 490 424 /** … … 494 428 * @note prints its own diagnostic information to stdout. 495 429 */ 496 int testSetProp(VBOXHGCMSVCFNTABLE *pTable) 497 { 498 int rc = VINF_SUCCESS; 499 RTPrintf("Testing the SET_PROP, SET_PROP_VALUE, SET_PROP_HOST and SET_PROP_VALUE_HOST calls.\n"); 500 for (unsigned i = 0; RT_SUCCESS(rc) && (setProperties[i].pcszName != NULL); 501 ++i) 502 { 503 rc = doSetProperty(pTable, setProperties[i].pcszName, 504 setProperties[i].pcszValue, 505 setProperties[i].pcszFlags, 506 setProperties[i].isHost, 507 setProperties[i].useSetProp); 508 if (setProperties[i].isAllowed && RT_FAILURE(rc)) 509 RTPrintf("Setting property '%s' failed with rc=%Rrc.\n", 510 setProperties[i].pcszName, rc); 511 else if ( !setProperties[i].isAllowed 512 && (rc != VERR_PERMISSION_DENIED)) 513 { 514 RTPrintf("Setting property '%s' returned %Rrc instead of VERR_PERMISSION_DENIED.\n", 515 setProperties[i].pcszName, rc); 516 rc = VERR_IPE_UNEXPECTED_STATUS; 517 } 518 else 519 rc = VINF_SUCCESS; 520 } 521 return rc; 430 static void testSetProp(VBOXHGCMSVCFNTABLE *pTable) 431 { 432 RTTestISub("SET_PROP, SET_PROP_VALUE, SET_PROP_HOST, SET_PROP_VALUE_HOST"); 433 434 /** Array of properties for testing SET_PROP_HOST and _GUEST. */ 435 static const struct 436 { 437 /** Property name */ 438 const char *pcszName; 439 /** Property value */ 440 const char *pcszValue; 441 /** Property flags */ 442 const char *pcszFlags; 443 /** Should this be set as the host or the guest? */ 444 bool isHost; 445 /** Should we use SET_PROP or SET_PROP_VALUE? */ 446 bool useSetProp; 447 /** Should this succeed or be rejected with VERR_PERMISSION_DENIED? */ 448 bool isAllowed; 449 } 450 s_aSetProperties[] = 451 { 452 { "Red", "Stop!", "transient", false, true, true }, 453 { "Amber", "Caution!", "", false, false, true }, 454 { "Green", "Go!", "readonly", true, true, true }, 455 { "Blue", "What on earth...?", "", true, false, true }, 456 { "/test/name", "test", "", false, true, false }, 457 { "TEST NAME", "test", "", true, true, false }, 458 { "Green", "gone out...", "", false, false, false }, 459 { "Green", "gone out...", "", true, false, false }, 460 }; 461 462 for (unsigned i = 0; i < RT_ELEMENTS(s_aSetProperties); ++i) 463 { 464 int rc = doSetProperty(pTable, 465 s_aSetProperties[i].pcszName, 466 s_aSetProperties[i].pcszValue, 467 s_aSetProperties[i].pcszFlags, 468 s_aSetProperties[i].isHost, 469 s_aSetProperties[i].useSetProp); 470 if (s_aSetProperties[i].isAllowed && RT_FAILURE(rc)) 471 RTTestIFailed("Setting property '%s' failed with rc=%Rrc.", 472 s_aSetProperties[i].pcszName, rc); 473 else if ( !s_aSetProperties[i].isAllowed 474 && rc != VERR_PERMISSION_DENIED) 475 RTTestIFailed("Setting property '%s' returned %Rrc instead of VERR_PERMISSION_DENIED.", 476 s_aSetProperties[i].pcszName, rc); 477 } 522 478 } 523 479 … … 531 487 * than the guest one 532 488 */ 533 int doDelProp(VBOXHGCMSVCFNTABLE *pTable, const char *pcszName, bool isHost)489 static int doDelProp(VBOXHGCMSVCFNTABLE *pTable, const char *pcszName, bool isHost) 534 490 { 535 491 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS }; … … 537 493 if (isHost) 538 494 command = DEL_PROP_HOST; 539 VBOXHGCMSVCPARM paParms[1];495 VBOXHGCMSVCPARM aParms[1]; 540 496 /* Work around silly constant issues - we ought to allow passing 541 497 * constant strings in the hgcm parameters. */ 542 498 char szName[MAX_NAME_LEN]; 543 499 RTStrPrintf(szName, sizeof(szName), "%s", pcszName); 544 paParms[0].setPointer (szName, (uint32_t)strlen(szName) + 1);500 aParms[0].setPointer (szName, (uint32_t)strlen(szName) + 1); 545 501 if (isHost) 546 callHandle.rc = pTable->pfnHostCall(pTable->pvService, command, 547 1, paParms); 502 callHandle.rc = pTable->pfnHostCall(pTable->pvService, command, 1, aParms); 548 503 else 549 pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL, command, 550 1, paParms); 504 pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL, command, 1, aParms); 551 505 return callHandle.rc; 552 506 } 553 554 /** Array of properties for testing DEL_PROP_HOST and _GUEST. */555 static const struct556 {557 /** Property name */558 const char *pcszName;559 /** Should this be set as the host or the guest? */560 bool isHost;561 /** Should this succeed or be rejected with VERR_PERMISSION_DENIED? */562 bool isAllowed;563 }564 delProperties[] =565 {566 { "Red", false, true },567 { "Amber", true, true },568 { "Red2", false, true },569 { "Amber2", true, true },570 { "Green", false, false },571 { "Green", true, false },572 { "/test/name", false, false },573 { "TEST NAME", true, false },574 { NULL, false, false }575 };576 507 577 508 /** … … 580 511 * @note prints its own diagnostic information to stdout. 581 512 */ 582 int testDelProp(VBOXHGCMSVCFNTABLE *pTable) 583 { 584 int rc = VINF_SUCCESS; 585 RTPrintf("Testing the DEL_PROP and DEL_PROP_HOST calls.\n"); 586 for (unsigned i = 0; RT_SUCCESS(rc) && (delProperties[i].pcszName != NULL); 587 ++i) 588 { 589 rc = doDelProp(pTable, delProperties[i].pcszName, 590 delProperties[i].isHost); 591 if (delProperties[i].isAllowed && RT_FAILURE(rc)) 592 RTPrintf("Deleting property '%s' failed with rc=%Rrc.\n", 593 delProperties[i].pcszName, rc); 594 else if ( !delProperties[i].isAllowed 595 && (rc != VERR_PERMISSION_DENIED) 596 ) 597 { 598 RTPrintf("Deleting property '%s' returned %Rrc instead of VERR_PERMISSION_DENIED.\n", 599 delProperties[i].pcszName, rc); 600 rc = VERR_IPE_UNEXPECTED_STATUS; 601 } 602 else 603 rc = VINF_SUCCESS; 604 } 605 return rc; 606 } 607 608 /** Array of properties for testing GET_PROP_HOST. */ 609 static const struct 610 { 611 /** Property name */ 612 const char *pcszName; 613 /** What value/flags pattern do we expect back? */ 614 const char *pcchValue; 615 /** What size should the value/flags array be? */ 616 uint32_t cchValue; 617 /** Should this property exist? */ 618 bool exists; 619 /** Do we expect a particular timestamp? */ 620 bool hasTimestamp; 621 /** What timestamp if any do ex expect? */ 622 uint64_t u64Timestamp; 623 } 624 getProperties[] = 625 { 626 { "test/name/", "test/value/\0", sizeof("test/value/\0"), true, true, 0 }, 627 { "test name", "test value\0TRANSIENT, READONLY", 628 sizeof("test value\0TRANSIENT, READONLY"), true, true, 999 }, 629 { "TEST NAME", "TEST VALUE\0RDONLYHOST", sizeof("TEST VALUE\0RDONLYHOST"), 630 true, true, 999999 }, 631 { "/test/name", "/test/value\0RDONLYGUEST", 632 sizeof("/test/value\0RDONLYGUEST"), true, true, UINT64_C(999999999999) }, 633 { "Green", "Go!\0READONLY", sizeof("Go!\0READONLY"), true, false, 0 }, 634 { "Blue", "What on earth...?\0", sizeof("What on earth...?\0"), true, 635 false, 0 }, 636 { "Red", "", 0, false, false, 0 }, 637 { NULL, NULL, 0, false, false, 0 } 638 }; 513 static void testDelProp(VBOXHGCMSVCFNTABLE *pTable) 514 { 515 RTTestISub("DEL_PROP, DEL_PROP_HOST"); 516 517 /** Array of properties for testing DEL_PROP_HOST and _GUEST. */ 518 static const struct 519 { 520 /** Property name */ 521 const char *pcszName; 522 /** Should this be set as the host or the guest? */ 523 bool isHost; 524 /** Should this succeed or be rejected with VERR_PERMISSION_DENIED? */ 525 bool isAllowed; 526 } 527 s_aDelProperties[] = 528 { 529 { "Red", false, true }, 530 { "Amber", true, true }, 531 { "Red2", false, true }, 532 { "Amber2", true, true }, 533 { "Green", false, false }, 534 { "Green", true, false }, 535 { "/test/name", false, false }, 536 { "TEST NAME", true, false }, 537 }; 538 539 for (unsigned i = 0; i < RT_ELEMENTS(s_aDelProperties); ++i) 540 { 541 int rc = doDelProp(pTable, s_aDelProperties[i].pcszName, 542 s_aDelProperties[i].isHost); 543 if (s_aDelProperties[i].isAllowed && RT_FAILURE(rc)) 544 RTTestIFailed("Deleting property '%s' failed with rc=%Rrc.", 545 s_aDelProperties[i].pcszName, rc); 546 else if ( !s_aDelProperties[i].isAllowed 547 && rc != VERR_PERMISSION_DENIED ) 548 RTTestIFailed("Deleting property '%s' returned %Rrc instead of VERR_PERMISSION_DENIED.", 549 s_aDelProperties[i].pcszName, rc); 550 } 551 } 639 552 640 553 /** … … 643 556 * @note prints its own diagnostic information to stdout. 644 557 */ 645 int testGetProp(VBOXHGCMSVCFNTABLE *pTable) 646 { 647 int rc = VINF_SUCCESS, rc2 = VINF_SUCCESS; 648 RTPrintf("Testing the GET_PROP_HOST call.\n"); 649 for (unsigned i = 0; RT_SUCCESS(rc) && (getProperties[i].pcszName != NULL); 650 ++i) 651 { 652 VBOXHGCMSVCPARM paParms[4]; 558 static void testGetProp(VBOXHGCMSVCFNTABLE *pTable) 559 { 560 RTTestISub("GET_PROP_HOST"); 561 562 /** Array of properties for testing GET_PROP_HOST. */ 563 static const struct 564 { 565 /** Property name */ 566 const char *pcszName; 567 /** What value/flags pattern do we expect back? */ 568 const char *pchValue; 569 /** What size should the value/flags array be? */ 570 uint32_t cchValue; 571 /** Should this property exist? */ 572 bool exists; 573 /** Do we expect a particular timestamp? */ 574 bool hasTimestamp; 575 /** What timestamp if any do ex expect? */ 576 uint64_t u64Timestamp; 577 } 578 s_aGetProperties[] = 579 { 580 { "test/name/", "test/value/\0", sizeof("test/value/\0"), true, true, 0 }, 581 { "test name", "test value\0TRANSIENT, READONLY", 582 sizeof("test value\0TRANSIENT, READONLY"), true, true, 999 }, 583 { "TEST NAME", "TEST VALUE\0RDONLYHOST", sizeof("TEST VALUE\0RDONLYHOST"), 584 true, true, 999999 }, 585 { "/test/name", "/test/value\0RDONLYGUEST", 586 sizeof("/test/value\0RDONLYGUEST"), true, true, UINT64_C(999999999999) }, 587 { "Green", "Go!\0READONLY", sizeof("Go!\0READONLY"), true, false, 0 }, 588 { "Blue", "What on earth...?\0", sizeof("What on earth...?\0"), true, 589 false, 0 }, 590 { "Red", "", 0, false, false, 0 }, 591 }; 592 593 for (unsigned i = 0; i < RT_ELEMENTS(s_aGetProperties); ++i) 594 { 595 VBOXHGCMSVCPARM aParms[4]; 653 596 /* Work around silly constant issues - we ought to allow passing 654 597 * constant strings in the hgcm parameters. */ 655 598 char szName[MAX_NAME_LEN] = ""; 656 599 char szBuffer[MAX_VALUE_LEN + MAX_FLAGS_LEN]; 657 AssertBreakStmt(sizeof(szBuffer) >= getProperties[i].cchValue, 658 rc = VERR_INTERNAL_ERROR); 659 RTStrPrintf(szName, sizeof(szName), "%s", getProperties[i].pcszName); 660 paParms[0].setPointer (szName, (uint32_t)strlen(szName) + 1); 661 paParms[1].setPointer (szBuffer, sizeof(szBuffer)); 662 rc2 = pTable->pfnHostCall(pTable->pvService, GET_PROP_HOST, 4, 663 paParms); 664 if (getProperties[i].exists && RT_FAILURE(rc2)) 665 { 666 RTPrintf("Getting property '%s' failed with rc=%Rrc.\n", 667 getProperties[i].pcszName, rc2); 668 rc = rc2; 669 } 670 else if (!getProperties[i].exists && (rc2 != VERR_NOT_FOUND)) 671 { 672 RTPrintf("Getting property '%s' returned %Rrc instead of VERR_NOT_FOUND.\n", 673 getProperties[i].pcszName, rc2); 674 rc = VERR_IPE_UNEXPECTED_STATUS; 675 } 676 if (RT_SUCCESS(rc) && getProperties[i].exists) 677 { 678 uint32_t u32ValueLen; 679 rc = paParms[3].getUInt32 (&u32ValueLen); 680 if (RT_FAILURE(rc)) 681 RTPrintf("Failed to get the size of the output buffer for property '%s'\n", 682 getProperties[i].pcszName); 683 if ( RT_SUCCESS(rc) 684 && (memcmp(szBuffer, getProperties[i].pcchValue, 685 getProperties[i].cchValue) != 0) 686 ) 600 RTTESTI_CHECK_RETV(s_aGetProperties[i].cchValue < sizeof(szBuffer)); 601 RTTESTI_CHECK_RETV(strlen(s_aGetProperties[i].pcszName) < sizeof(szName)); 602 603 strcpy(szName, s_aGetProperties[i].pcszName); 604 aParms[0].setPointer(szName, (uint32_t)(strlen(szName) + 1)); 605 aParms[1].setPointer(szBuffer, sizeof(szBuffer)); 606 int rc2 = pTable->pfnHostCall(pTable->pvService, GET_PROP_HOST, 4, aParms); 607 608 if (s_aGetProperties[i].exists && RT_FAILURE(rc2)) 609 { 610 RTTestIFailed("Getting property '%s' failed with rc=%Rrc.", 611 s_aGetProperties[i].pcszName, rc2); 612 continue; 613 } 614 615 if (!s_aGetProperties[i].exists && rc2 != VERR_NOT_FOUND) 616 { 617 RTTestIFailed("Getting property '%s' returned %Rrc instead of VERR_NOT_FOUND.", 618 s_aGetProperties[i].pcszName, rc2); 619 continue; 620 } 621 622 if (s_aGetProperties[i].exists) 623 { 624 AssertRC(rc2); 625 626 uint32_t u32ValueLen = UINT32_MAX; 627 RTTESTI_CHECK_RC(rc2 = aParms[3].getUInt32(&u32ValueLen), VINF_SUCCESS); 628 if (RT_SUCCESS(rc2)) 687 629 { 688 RTPrintf("Unexpected result '%.*s' for property '%s', expected '%.*s'.\n", 689 u32ValueLen, szBuffer, getProperties[i].pcszName, 690 getProperties[i].cchValue, getProperties[i].pcchValue); 691 rc = VERR_UNRESOLVED_ERROR; 630 RTTESTI_CHECK_MSG(u32ValueLen <= sizeof(szBuffer), ("u32ValueLen=%d", u32ValueLen)); 631 if (memcmp(szBuffer, s_aGetProperties[i].pchValue, s_aGetProperties[i].cchValue) != 0) 632 RTTestIFailed("Unexpected result '%.*s' for property '%s', expected '%.*s'.", 633 u32ValueLen, szBuffer, s_aGetProperties[i].pcszName, 634 s_aGetProperties[i].cchValue, s_aGetProperties[i].pchValue); 692 635 } 693 if (RT_SUCCESS(rc) && getProperties[i].hasTimestamp) 636 637 if (s_aGetProperties[i].hasTimestamp) 694 638 { 695 uint64_t u64Timestamp; 696 rc = paParms[2].getUInt64 (&u64Timestamp); 697 if (RT_FAILURE(rc)) 698 RTPrintf("Failed to get the timestamp for property '%s'\n", 699 getProperties[i].pcszName); 700 if ( RT_SUCCESS(rc) 701 && (u64Timestamp != getProperties[i].u64Timestamp) 702 ) 703 { 704 RTPrintf("Bad timestamp %llu for property '%s', expected %llu.\n", 705 u64Timestamp, getProperties[i].pcszName, 706 getProperties[i].u64Timestamp); 707 rc = VERR_UNRESOLVED_ERROR; 708 } 639 uint64_t u64Timestamp = UINT64_MAX; 640 RTTESTI_CHECK_RC(rc2 = aParms[2].getUInt64(&u64Timestamp), VINF_SUCCESS); 641 if (u64Timestamp != s_aGetProperties[i].u64Timestamp) 642 RTTestIFailed("Bad timestamp %llu for property '%s', expected %llu.", 643 u64Timestamp, s_aGetProperties[i].pcszName, 644 s_aGetProperties[i].u64Timestamp); 709 645 } 710 646 } 711 647 } 712 return rc;713 648 } 714 649 … … 719 654 const char *pchBuffer; 720 655 /** What size should the buffer be? */ 721 uint32_t c chBuffer;722 } 723 g etNotifications[] =656 uint32_t cbBuffer; 657 } 658 g_aGetNotifications[] = 724 659 { 725 660 { "Red\0Stop!\0TRANSIENT", sizeof("Red\0Stop!\0TRANSIENT") }, … … 729 664 { "Red\0\0", sizeof("Red\0\0") }, 730 665 { "Amber\0\0", sizeof("Amber\0\0") }, 731 { NULL, 0 }732 666 }; 733 667 … … 737 671 * @note prints its own diagnostic information to stdout. 738 672 */ 739 int testGetNotification(VBOXHGCMSVCFNTABLE *pTable) 740 { 741 int rc = VINF_SUCCESS; 742 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS }; 743 char achBuffer[MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN]; 744 static char szPattern[] = ""; 745 746 RTPrintf("Testing the GET_NOTIFICATION call.\n"); 747 uint64_t u64Timestamp; 748 uint32_t u32Size = 0; 749 VBOXHGCMSVCPARM paParms[4]; 673 static void testGetNotification(VBOXHGCMSVCFNTABLE *pTable) 674 { 675 RTTestISub("GET_NOTIFICATION"); 750 676 751 677 /* Test "buffer too small" */ 752 u64Timestamp = 1; 753 paParms[0].setPointer ((void *) szPattern, sizeof(szPattern)); 754 paParms[1].setUInt64 (u64Timestamp); 755 paParms[2].setPointer ((void *) achBuffer, getNotifications[0].cchBuffer - 1); 756 pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL, 757 GET_NOTIFICATION, 4, paParms); 678 char achBuffer[MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN]; 679 static char s_szPattern[] = ""; 680 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS }; 681 VBOXHGCMSVCPARM aParms[4]; 682 aParms[0].setPointer((void *)s_szPattern, sizeof(s_szPattern)); 683 aParms[1].setUInt64(1); 684 aParms[2].setPointer((void *)achBuffer, g_aGetNotifications[0].cbBuffer - 1); 685 pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL, GET_NOTIFICATION, 4, aParms); 686 687 uint32_t cbRetNeeded; 758 688 if ( callHandle.rc != VERR_BUFFER_OVERFLOW 759 || RT_FAILURE( paParms[3].getUInt32 (&u32Size))760 || u32Size != getNotifications[0].cchBuffer689 || RT_FAILURE(aParms[3].getUInt32(&cbRetNeeded)) 690 || cbRetNeeded != g_aGetNotifications[0].cbBuffer 761 691 ) 762 692 { 763 RT Printf("Getting notification for property '%s' with a too small buffer did not fail correctly.\n",764 getNotifications[0].pchBuffer);765 r c = VERR_UNRESOLVED_ERROR;693 RTTestIFailed("Getting notification for property '%s' with a too small buffer did not fail correctly.", 694 g_aGetNotifications[0].pchBuffer); 695 return; 766 696 } 767 697 768 698 /* Test successful notification queries. Start with an unknown timestamp 769 699 * to get the oldest available notification. */ 770 u64Timestamp = 1; 771 for (unsigned i = 0; RT_SUCCESS(rc) && (getNotifications[i].pchBuffer != NULL); 772 ++i) 773 { 774 paParms[0].setPointer ((void *) szPattern, sizeof(szPattern)); 775 paParms[1].setUInt64 (u64Timestamp); 776 paParms[2].setPointer ((void *) achBuffer, sizeof(achBuffer)); 777 pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL, 778 GET_NOTIFICATION, 4, paParms); 700 uint64_t u64Timestamp = 1; 701 for (unsigned i = 0; i < RT_ELEMENTS(g_aGetNotifications); ++i) 702 { 703 aParms[0].setPointer((void *)s_szPattern, sizeof(s_szPattern)); 704 aParms[1].setUInt64(u64Timestamp); 705 aParms[2].setPointer((void *)achBuffer, sizeof(achBuffer)); 706 pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL, GET_NOTIFICATION, 4, aParms); 779 707 if ( RT_FAILURE(callHandle.rc) 780 708 || (i == 0 && callHandle.rc != VWRN_NOT_FOUND) 781 || RT_FAILURE( paParms[1].getUInt64(&u64Timestamp))782 || RT_FAILURE( paParms[3].getUInt32 (&u32Size))783 || u32Size != getNotifications[i].cchBuffer784 || memcmp(achBuffer, g etNotifications[i].pchBuffer, u32Size) != 0709 || RT_FAILURE(aParms[1].getUInt64(&u64Timestamp)) 710 || RT_FAILURE(aParms[3].getUInt32(&cbRetNeeded)) 711 || cbRetNeeded != g_aGetNotifications[i].cbBuffer 712 || memcmp(achBuffer, g_aGetNotifications[i].pchBuffer, cbRetNeeded) != 0 785 713 ) 786 714 { 787 RTPrintf("Failed to get notification for property '%s' (rc=%Rrc).\n", 788 getNotifications[i].pchBuffer, rc); 789 rc = VERR_UNRESOLVED_ERROR; 790 } 791 } 792 return rc; 715 RTTestIFailed("Failed to get notification for property '%s' (rc=%Rrc).", 716 g_aGetNotifications[i].pchBuffer, callHandle.rc); 717 } 718 } 793 719 } 794 720 … … 799 725 VBOXHGCMSVCPARM aParms[4]; 800 726 /** Result buffer */ 801 char chBuffer[MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN];727 char abBuffer[MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN]; 802 728 /** Return value */ 803 729 VBOXHGCMCALLHANDLE_TYPEDEF callHandle; 804 } asyncNotification;730 } g_AsyncNotification; 805 731 806 732 /** 807 733 * Set up the test for the asynchronous GET_NOTIFICATION function. 808 * @returns iprt status value to indicate whether the test went as expected. 809 * @note prints its own diagnostic information to stdout. 810 */ 811 int setupAsyncNotification(VBOXHGCMSVCFNTABLE *pTable) 812 { 813 int rc = VINF_SUCCESS; 814 815 RTPrintf("Testing the asynchronous GET_NOTIFICATION call with no notifications are available.\n"); 816 uint64_t u64Timestamp = 0; 817 uint32_t u32Size = 0; 818 static char szPattern[] = ""; 819 820 asyncNotification.aParms[0].setPointer ((void *) szPattern, sizeof(szPattern)); 821 asyncNotification.aParms[1].setUInt64 (u64Timestamp); 822 asyncNotification.aParms[2].setPointer ((void *) asyncNotification.chBuffer, 823 sizeof(asyncNotification.chBuffer)); 824 asyncNotification.callHandle.rc = VINF_HGCM_ASYNC_EXECUTE; 825 pTable->pfnCall(pTable->pvService, &asyncNotification.callHandle, 0, NULL, 826 GET_NOTIFICATION, 4, asyncNotification.aParms); 827 if (RT_FAILURE(asyncNotification.callHandle.rc)) 828 { 829 RTPrintf("GET_NOTIFICATION call failed, rc=%Rrc.\n", asyncNotification.callHandle.rc); 830 rc = VERR_UNRESOLVED_ERROR; 831 } 832 else if (asyncNotification.callHandle.rc != VINF_HGCM_ASYNC_EXECUTE) 833 { 834 RTPrintf("GET_NOTIFICATION call completed when no new notifications should be available.\n"); 835 rc = VERR_UNRESOLVED_ERROR; 836 } 837 return rc; 734 */ 735 static void setupAsyncNotification(VBOXHGCMSVCFNTABLE *pTable) 736 { 737 RTTestISub("Asynchronous GET_NOTIFICATION call with no notifications are available"); 738 static char s_szPattern[] = ""; 739 740 g_AsyncNotification.aParms[0].setPointer((void *)s_szPattern, sizeof(s_szPattern)); 741 g_AsyncNotification.aParms[1].setUInt64(0); 742 g_AsyncNotification.aParms[2].setPointer((void *)g_AsyncNotification.abBuffer, 743 sizeof(g_AsyncNotification.abBuffer)); 744 g_AsyncNotification.callHandle.rc = VINF_HGCM_ASYNC_EXECUTE; 745 pTable->pfnCall(pTable->pvService, &g_AsyncNotification.callHandle, 0, NULL, 746 GET_NOTIFICATION, 4, g_AsyncNotification.aParms); 747 if (RT_FAILURE(g_AsyncNotification.callHandle.rc)) 748 RTTestIFailed("GET_NOTIFICATION call failed, rc=%Rrc.", g_AsyncNotification.callHandle.rc); 749 else if (g_AsyncNotification.callHandle.rc != VINF_HGCM_ASYNC_EXECUTE) 750 RTTestIFailed("GET_NOTIFICATION call completed when no new notifications should be available."); 838 751 } 839 752 840 753 /** 841 754 * Test the asynchronous GET_NOTIFICATION function. 842 * @returns iprt status value to indicate whether the test went as expected. 843 * @note prints its own diagnostic information to stdout. 844 */ 845 int testAsyncNotification(VBOXHGCMSVCFNTABLE *pTable) 846 { 847 int rc = VINF_SUCCESS; 755 */ 756 static void testAsyncNotification(VBOXHGCMSVCFNTABLE *pTable) 757 { 848 758 uint64_t u64Timestamp; 849 759 uint32_t u32Size; 850 if ( asyncNotification.callHandle.rc != VINF_SUCCESS851 || RT_FAILURE( asyncNotification.aParms[1].getUInt64(&u64Timestamp))852 || RT_FAILURE( asyncNotification.aParms[3].getUInt32(&u32Size))853 || u32Size != g etNotifications[0].cchBuffer854 || memcmp( asyncNotification.chBuffer, getNotifications[0].pchBuffer, u32Size) != 0760 if ( g_AsyncNotification.callHandle.rc != VINF_SUCCESS 761 || RT_FAILURE(g_AsyncNotification.aParms[1].getUInt64(&u64Timestamp)) 762 || RT_FAILURE(g_AsyncNotification.aParms[3].getUInt32(&u32Size)) 763 || u32Size != g_aGetNotifications[0].cbBuffer 764 || memcmp(g_AsyncNotification.abBuffer, g_aGetNotifications[0].pchBuffer, u32Size) != 0 855 765 ) 856 766 { 857 RTPrintf("Asynchronous GET_NOTIFICATION call did not complete as expected, rc=%Rrc\n", 858 asyncNotification.callHandle.rc); 859 rc = VERR_UNRESOLVED_ERROR; 860 } 861 return rc; 862 } 863 864 /** Array of properties for testing SET_PROP_HOST and _GUEST with the 865 * READONLYGUEST global flag set. */ 866 static const struct 867 { 868 /** Property name */ 869 const char *pcszName; 870 /** Property value */ 871 const char *pcszValue; 872 /** Property flags */ 873 const char *pcszFlags; 874 /** Should this be set as the host or the guest? */ 875 bool isHost; 876 /** Should we use SET_PROP or SET_PROP_VALUE? */ 877 bool useSetProp; 878 /** Should this succeed or be rejected with VERR_ (NOT VINF_!) 879 * PERMISSION_DENIED? The global check is done after the property one. */ 880 bool isAllowed; 881 } 882 setPropertiesROGuest[] = 883 { 884 { "Red", "Stop!", "transient", false, true, true }, 885 { "Amber", "Caution!", "", false, false, true }, 886 { "Green", "Go!", "readonly", true, true, true }, 887 { "Blue", "What on earth...?", "", true, false, true }, 888 { "/test/name", "test", "", false, true, true }, 889 { "TEST NAME", "test", "", true, true, true }, 890 { "Green", "gone out...", "", false, false, false }, 891 { "Green", "gone out....", "", true, false, false }, 892 { NULL, NULL, NULL, false, false, true } 893 }; 767 RTTestIFailed("Asynchronous GET_NOTIFICATION call did not complete as expected, rc=%Rrc.", 768 g_AsyncNotification.callHandle.rc); 769 } 770 } 771 772 773 static void test2(void) 774 { 775 VBOXHGCMSVCFNTABLE svcTable; 776 VBOXHGCMSVCHELPERS svcHelpers; 777 initTable(&svcTable, &svcHelpers); 778 779 /* The function is inside the service, not HGCM. */ 780 RTTESTI_CHECK_RC_OK_RETV(VBoxHGCMSvcLoad(&svcTable)); 781 782 testSetPropsHost(&svcTable); 783 testEnumPropsHost(&svcTable); 784 785 /* Set up the asynchronous notification test */ 786 setupAsyncNotification(&svcTable); 787 testSetProp(&svcTable); 788 RTTestISub("Checking the data returned by the asynchronous notification call"); 789 testAsyncNotification(&svcTable); /* Our previous notification call should have completed by now. */ 790 791 testDelProp(&svcTable); 792 testGetProp(&svcTable); 793 testGetNotification(&svcTable); 794 795 /* Cleanup */ 796 RTTESTI_CHECK_RC_OK(svcTable.pfnUnload(svcTable.pvService)); 797 } 894 798 895 799 /** … … 900 804 * @param eFlags the flags to set 901 805 */ 902 int doSetGlobalFlags(VBOXHGCMSVCFNTABLE *pTable, ePropFlags eFlags)806 static int doSetGlobalFlags(VBOXHGCMSVCFNTABLE *pTable, ePropFlags eFlags) 903 807 { 904 808 VBOXHGCMSVCPARM paParm; 905 809 paParm.setUInt32(eFlags); 906 int rc = pTable->pfnHostCall(pTable->pvService, SET_GLOBAL_FLAGS_HOST, 907 1, &paParm); 810 int rc = pTable->pfnHostCall(pTable->pvService, SET_GLOBAL_FLAGS_HOST, 1, &paParm); 908 811 if (RT_FAILURE(rc)) 909 812 { 910 813 char szFlags[MAX_FLAGS_LEN]; 911 814 if (RT_FAILURE(writeFlags(eFlags, szFlags))) 912 RT Printf("Failed to set the global flags.\n");815 RTTestIFailed("Failed to set the global flags."); 913 816 else 914 RTPrintf("Failed to set the global flags \"%s\".\n", 915 szFlags); 817 RTTestIFailed("Failed to set the global flags \"%s\".", szFlags); 916 818 } 917 819 return rc; … … 924 826 * @note prints its own diagnostic information to stdout. 925 827 */ 926 int testSetPropROGuest(VBOXHGCMSVCFNTABLE *pTable) 927 { 928 int rc = VINF_SUCCESS; 929 RTPrintf("Testing the SET_PROP, SET_PROP_VALUE, SET_PROP_HOST and SET_PROP_VALUE_HOST calls with READONLYGUEST set globally.\n"); 930 rc = VBoxHGCMSvcLoad(pTable); 931 if (RT_FAILURE(rc)) 932 RTPrintf("Failed to start the HGCM service.\n"); 828 static void testSetPropROGuest(VBOXHGCMSVCFNTABLE *pTable) 829 { 830 RTTestISub("SET_PROP, SET_PROP_VALUE, SET_PROP_HOST and SET_PROP_VALUE_HOST calls with READONLYGUEST set globally"); 831 832 /** Array of properties for testing SET_PROP_HOST and _GUEST with the 833 * READONLYGUEST global flag set. */ 834 static const struct 835 { 836 /** Property name */ 837 const char *pcszName; 838 /** Property value */ 839 const char *pcszValue; 840 /** Property flags */ 841 const char *pcszFlags; 842 /** Should this be set as the host or the guest? */ 843 bool isHost; 844 /** Should we use SET_PROP or SET_PROP_VALUE? */ 845 bool useSetProp; 846 /** Should this succeed or be rejected with VERR_ (NOT VINF_!) 847 * PERMISSION_DENIED? The global check is done after the property one. */ 848 bool isAllowed; 849 } 850 s_aSetPropertiesROGuest[] = 851 { 852 { "Red", "Stop!", "transient", false, true, true }, 853 { "Amber", "Caution!", "", false, false, true }, 854 { "Green", "Go!", "readonly", true, true, true }, 855 { "Blue", "What on earth...?", "", true, false, true }, 856 { "/test/name", "test", "", false, true, true }, 857 { "TEST NAME", "test", "", true, true, true }, 858 { "Green", "gone out...", "", false, false, false }, 859 { "Green", "gone out....", "", true, false, false }, 860 }; 861 862 RTTESTI_CHECK_RC_OK_RETV(VBoxHGCMSvcLoad(pTable)); 863 int rc = doSetGlobalFlags(pTable, RDONLYGUEST); 933 864 if (RT_SUCCESS(rc)) 934 rc = doSetGlobalFlags(pTable, RDONLYGUEST); 935 for (unsigned i = 0; RT_SUCCESS(rc) && (setPropertiesROGuest[i].pcszName != NULL); 936 ++i) 937 { 938 rc = doSetProperty(pTable, setPropertiesROGuest[i].pcszName, 939 setPropertiesROGuest[i].pcszValue, 940 setPropertiesROGuest[i].pcszFlags, 941 setPropertiesROGuest[i].isHost, 942 setPropertiesROGuest[i].useSetProp); 943 if (setPropertiesROGuest[i].isAllowed && RT_FAILURE(rc)) 944 RTPrintf("Setting property '%s' to '%s' failed with rc=%Rrc.\n", 945 setPropertiesROGuest[i].pcszName, 946 setPropertiesROGuest[i].pcszValue, rc); 947 else if ( !setPropertiesROGuest[i].isAllowed 948 && (rc != VERR_PERMISSION_DENIED)) 949 { 950 RTPrintf("Setting property '%s' to '%s' returned %Rrc instead of VERR_PERMISSION_DENIED.\n", 951 setPropertiesROGuest[i].pcszName, 952 setPropertiesROGuest[i].pcszValue, rc); 953 rc = VERR_IPE_UNEXPECTED_STATUS; 954 } 955 else if ( !setPropertiesROGuest[i].isHost 956 && setPropertiesROGuest[i].isAllowed 957 && (rc != VINF_PERMISSION_DENIED)) 958 { 959 RTPrintf("Setting property '%s' to '%s' returned %Rrc instead of VINF_PERMISSION_DENIED.\n", 960 setPropertiesROGuest[i].pcszName, 961 setPropertiesROGuest[i].pcszValue, rc); 962 rc = VERR_IPE_UNEXPECTED_STATUS; 963 } 964 else 965 rc = VINF_SUCCESS; 966 } 967 if (RT_FAILURE(pTable->pfnUnload(pTable->pvService))) 968 RTPrintf("Failed to unload the HGCM service.\n"); 969 return rc; 970 } 971 972 /** Array of properties for testing DEL_PROP_HOST and _GUEST with 973 * READONLYGUEST set globally. */ 974 static const struct 975 { 976 /** Property name */ 977 const char *pcszName; 978 /** Should this be deleted as the host (or the guest)? */ 979 bool isHost; 980 /** Should this property be created first? (As host, obviously) */ 981 bool shouldCreate; 982 /** And with what flags? */ 983 const char *pcszFlags; 984 /** Should this succeed or be rejected with VERR_ (NOT VINF_!) 985 * PERMISSION_DENIED? The global check is done after the property one. */ 986 bool isAllowed; 987 } 988 delPropertiesROGuest[] = 989 { 990 { "Red", true, true, "", true }, 991 { "Amber", false, true, "", true }, 992 { "Red2", true, false, "", true }, 993 { "Amber2", false, false, "", true }, 994 { "Red3", true, true, "READONLY", false }, 995 { "Amber3", false, true, "READONLY", false }, 996 { "Red4", true, true, "RDONLYHOST", false }, 997 { "Amber4", false, true, "RDONLYHOST", true }, 998 { NULL, false, false, "", false } 999 }; 865 { 866 for (unsigned i = 0; i < RT_ELEMENTS(s_aSetPropertiesROGuest); ++i) 867 { 868 rc = doSetProperty(pTable, s_aSetPropertiesROGuest[i].pcszName, 869 s_aSetPropertiesROGuest[i].pcszValue, 870 s_aSetPropertiesROGuest[i].pcszFlags, 871 s_aSetPropertiesROGuest[i].isHost, 872 s_aSetPropertiesROGuest[i].useSetProp); 873 if (s_aSetPropertiesROGuest[i].isAllowed && RT_FAILURE(rc)) 874 RTTestIFailed("Setting property '%s' to '%s' failed with rc=%Rrc.", 875 s_aSetPropertiesROGuest[i].pcszName, 876 s_aSetPropertiesROGuest[i].pcszValue, rc); 877 else if ( !s_aSetPropertiesROGuest[i].isAllowed 878 && rc != VERR_PERMISSION_DENIED) 879 RTTestIFailed("Setting property '%s' to '%s' returned %Rrc instead of VERR_PERMISSION_DENIED.\n", 880 s_aSetPropertiesROGuest[i].pcszName, 881 s_aSetPropertiesROGuest[i].pcszValue, rc); 882 else if ( !s_aSetPropertiesROGuest[i].isHost 883 && s_aSetPropertiesROGuest[i].isAllowed 884 && rc != VINF_PERMISSION_DENIED) 885 RTTestIFailed("Setting property '%s' to '%s' returned %Rrc instead of VINF_PERMISSION_DENIED.\n", 886 s_aSetPropertiesROGuest[i].pcszName, 887 s_aSetPropertiesROGuest[i].pcszValue, rc); 888 } 889 } 890 RTTESTI_CHECK_RC_OK(pTable->pfnUnload(pTable->pvService)); 891 } 1000 892 1001 893 /** … … 1004 896 * @note prints its own diagnostic information to stdout. 1005 897 */ 1006 int testDelPropROGuest(VBOXHGCMSVCFNTABLE *pTable) 1007 { 1008 int rc = VINF_SUCCESS; 1009 RTPrintf("Testing the DEL_PROP and DEL_PROP_HOST calls with RDONLYGUEST set globally.\n"); 1010 rc = VBoxHGCMSvcLoad(pTable); 1011 if (RT_FAILURE(rc)) 1012 RTPrintf("Failed to start the HGCM service.\n"); 898 static void testDelPropROGuest(VBOXHGCMSVCFNTABLE *pTable) 899 { 900 RTTestISub("DEL_PROP and DEL_PROP_HOST calls with RDONLYGUEST set globally"); 901 902 /** Array of properties for testing DEL_PROP_HOST and _GUEST with 903 * READONLYGUEST set globally. */ 904 static const struct 905 { 906 /** Property name */ 907 const char *pcszName; 908 /** Should this be deleted as the host (or the guest)? */ 909 bool isHost; 910 /** Should this property be created first? (As host, obviously) */ 911 bool shouldCreate; 912 /** And with what flags? */ 913 const char *pcszFlags; 914 /** Should this succeed or be rejected with VERR_ (NOT VINF_!) 915 * PERMISSION_DENIED? The global check is done after the property one. */ 916 bool isAllowed; 917 } 918 s_aDelPropertiesROGuest[] = 919 { 920 { "Red", true, true, "", true }, 921 { "Amber", false, true, "", true }, 922 { "Red2", true, false, "", true }, 923 { "Amber2", false, false, "", true }, 924 { "Red3", true, true, "READONLY", false }, 925 { "Amber3", false, true, "READONLY", false }, 926 { "Red4", true, true, "RDONLYHOST", false }, 927 { "Amber4", false, true, "RDONLYHOST", true }, 928 }; 929 930 RTTESTI_CHECK_RC_OK_RETV(VBoxHGCMSvcLoad(pTable)); 931 int rc = doSetGlobalFlags(pTable, RDONLYGUEST); 1013 932 if (RT_SUCCESS(rc)) 1014 rc = doSetGlobalFlags(pTable, RDONLYGUEST); 1015 for (unsigned i = 0; RT_SUCCESS(rc) 1016 && (delPropertiesROGuest[i].pcszName != NULL); ++i) 1017 { 1018 if (RT_SUCCESS(rc) && delPropertiesROGuest[i].shouldCreate) 1019 rc = doSetProperty(pTable, delPropertiesROGuest[i].pcszName, 1020 "none", delPropertiesROGuest[i].pcszFlags, 1021 true, true); 1022 rc = doDelProp(pTable, delPropertiesROGuest[i].pcszName, 1023 delPropertiesROGuest[i].isHost); 1024 if (delPropertiesROGuest[i].isAllowed && RT_FAILURE(rc)) 1025 RTPrintf("Deleting property '%s' failed with rc=%Rrc.\n", 1026 delPropertiesROGuest[i].pcszName, rc); 1027 else if ( !delPropertiesROGuest[i].isAllowed 1028 && (rc != VERR_PERMISSION_DENIED) 1029 ) 1030 { 1031 RTPrintf("Deleting property '%s' returned %Rrc instead of VERR_PERMISSION_DENIED.\n", 1032 delPropertiesROGuest[i].pcszName, rc); 1033 rc = VERR_IPE_UNEXPECTED_STATUS; 1034 } 1035 else if ( !delPropertiesROGuest[i].isHost 1036 && delPropertiesROGuest[i].shouldCreate 1037 && delPropertiesROGuest[i].isAllowed 1038 && (rc != VINF_PERMISSION_DENIED)) 1039 { 1040 RTPrintf("Deleting property '%s' as guest returned %Rrc instead of VINF_PERMISSION_DENIED.\n", 1041 delPropertiesROGuest[i].pcszName, rc); 1042 rc = VERR_IPE_UNEXPECTED_STATUS; 1043 } 1044 else 1045 rc = VINF_SUCCESS; 1046 } 1047 if (RT_FAILURE(pTable->pfnUnload(pTable->pvService))) 1048 RTPrintf("Failed to unload the HGCM service.\n"); 1049 return rc; 1050 } 1051 1052 int main(int argc, char **argv) 933 { 934 for (unsigned i = 0; i < RT_ELEMENTS(s_aDelPropertiesROGuest); ++i) 935 { 936 if (s_aDelPropertiesROGuest[i].shouldCreate) 937 rc = doSetProperty(pTable, s_aDelPropertiesROGuest[i].pcszName, 938 "none", s_aDelPropertiesROGuest[i].pcszFlags, 939 true, true); 940 rc = doDelProp(pTable, s_aDelPropertiesROGuest[i].pcszName, 941 s_aDelPropertiesROGuest[i].isHost); 942 if (s_aDelPropertiesROGuest[i].isAllowed && RT_FAILURE(rc)) 943 RTTestIFailed("Deleting property '%s' failed with rc=%Rrc.", 944 s_aDelPropertiesROGuest[i].pcszName, rc); 945 else if ( !s_aDelPropertiesROGuest[i].isAllowed 946 && rc != VERR_PERMISSION_DENIED) 947 RTTestIFailed("Deleting property '%s' returned %Rrc instead of VERR_PERMISSION_DENIED.", 948 s_aDelPropertiesROGuest[i].pcszName, rc); 949 else if ( !s_aDelPropertiesROGuest[i].isHost 950 && s_aDelPropertiesROGuest[i].shouldCreate 951 && s_aDelPropertiesROGuest[i].isAllowed 952 && rc != VINF_PERMISSION_DENIED) 953 RTTestIFailed("Deleting property '%s' as guest returned %Rrc instead of VINF_PERMISSION_DENIED.", 954 s_aDelPropertiesROGuest[i].pcszName, rc); 955 } 956 } 957 RTTESTI_CHECK_RC_OK(pTable->pfnUnload(pTable->pvService)); 958 } 959 960 static void test3(void) 1053 961 { 1054 962 VBOXHGCMSVCFNTABLE svcTable; 1055 963 VBOXHGCMSVCHELPERS svcHelpers; 1056 RTEXITCODE rcExit; 1057 1058 rcExit = RTTestInitAndCreate("tstGuestPropSvc", &g_hTest); 964 initTable(&svcTable, &svcHelpers); 965 testSetPropROGuest(&svcTable); 966 testDelPropROGuest(&svcTable); 967 } 968 969 970 static void test4(void) 971 { 972 RTTestISub("Max properties"); 973 974 VBOXHGCMSVCFNTABLE svcTable; 975 VBOXHGCMSVCHELPERS svcHelpers; 976 initTable(&svcTable, &svcHelpers); 977 RTTESTI_CHECK_RC_OK_RETV(VBoxHGCMSvcLoad(&svcTable)); 978 979 /* Insert the max number of properties. */ 980 static char const s_szPropFmt[] = "/MyProperties/Sub/Sub/Sub/Sub/Sub/Sub/Sub/PropertyNo#%u"; 981 char szProp[80]; 982 unsigned cProps = 0; 983 for (;;) 984 { 985 RTStrPrintf(szProp, sizeof(szProp), s_szPropFmt, cProps); 986 int rc = doSetProperty(&svcTable, szProp, "myvalue", "", true, true); 987 if (rc == VERR_TOO_MUCH_DATA) 988 break; 989 if (RT_FAILURE(rc)) 990 { 991 RTTestIFailed("Unexpected error %Rrc setting property number %u", rc, cProps); 992 break; 993 } 994 cProps++; 995 } 996 RTTestIValue("Max Properties", cProps, RTTESTUNIT_OCCURRENCES); 997 998 /* Touch them all again. */ 999 for (unsigned iProp = 0; iProp < cProps; iProp++) 1000 { 1001 RTStrPrintf(szProp, sizeof(szProp), s_szPropFmt, iProp); 1002 int rc; 1003 RTTESTI_CHECK_MSG((rc = doSetProperty(&svcTable, szProp, "myvalue", "", true, true)) == VINF_SUCCESS, 1004 ("%Rrc - #%u\n", rc, iProp)); 1005 RTTESTI_CHECK_MSG((rc = doSetProperty(&svcTable, szProp, "myvalue", "", true, false)) == VINF_SUCCESS, 1006 ("%Rrc - #%u\n", rc, iProp)); 1007 RTTESTI_CHECK_MSG((rc = doSetProperty(&svcTable, szProp, "myvalue", "", false, true)) == VINF_SUCCESS, 1008 ("%Rrc - #%u\n", rc, iProp)); 1009 RTTESTI_CHECK_MSG((rc = doSetProperty(&svcTable, szProp, "myvalue", "", false, false)) == VINF_SUCCESS, 1010 ("%Rrc - #%u\n", rc, iProp)); 1011 } 1012 1013 /* Benchmark. */ 1014 uint64_t cNsMax = 0; 1015 uint64_t cNsMin = UINT64_MAX; 1016 uint64_t cNsAvg = 0; 1017 for (unsigned iProp = 0; iProp < cProps; iProp++) 1018 { 1019 size_t cchProp = RTStrPrintf(szProp, sizeof(szProp), s_szPropFmt, iProp); 1020 1021 uint64_t cNsElapsed = RTTimeNanoTS(); 1022 unsigned iCall; 1023 for (iCall = 0; iCall < 1000; iCall++) 1024 { 1025 VBOXHGCMSVCPARM aParms[4]; 1026 char szBuffer[256]; 1027 aParms[0].setPointer(szProp, cchProp + 1); 1028 aParms[1].setPointer(szBuffer, sizeof(szBuffer)); 1029 RTTESTI_CHECK_RC_BREAK(svcTable.pfnHostCall(svcTable.pvService, GET_PROP_HOST, 4, aParms), VINF_SUCCESS); 1030 } 1031 cNsElapsed = RTTimeNanoTS() - cNsElapsed; 1032 if (iCall) 1033 { 1034 uint64_t cNsPerCall = cNsElapsed / iCall; 1035 cNsAvg += cNsPerCall; 1036 if (cNsPerCall < cNsMin) 1037 cNsMin = cNsPerCall; 1038 if (cNsPerCall > cNsMax) 1039 cNsMax = cNsPerCall; 1040 } 1041 } 1042 if (cProps) 1043 cNsAvg /= cProps; 1044 RTTestIValue("GET_PROP_HOST Min", cNsMin, RTTESTUNIT_NS_PER_CALL); 1045 RTTestIValue("GET_PROP_HOST Avg", cNsAvg, RTTESTUNIT_NS_PER_CALL); 1046 RTTestIValue("GET_PROP_HOST Max", cNsMax, RTTESTUNIT_NS_PER_CALL); 1047 1048 /* Done. */ 1049 RTTESTI_CHECK_RC_OK(svcTable.pfnUnload(svcTable.pvService)); 1050 } 1051 1052 1053 int main(int argc, char **argv) 1054 { 1055 RTEXITCODE rcExit = RTTestInitAndCreate("tstGuestPropSvc", &g_hTest); 1059 1056 if (rcExit != RTEXITCODE_SUCCESS) 1060 1057 return rcExit; 1061 1058 RTTestBanner(g_hTest); 1062 1059 1063 /** @todo convert the rest of this testcase. */ 1064 initTable(&svcTable, &svcHelpers); 1065 1066 if (RT_FAILURE(testConvertFlags())) 1067 return 1; 1068 /* The function is inside the service, not HGCM. */ 1069 if (RT_FAILURE(VBoxHGCMSvcLoad(&svcTable))) 1070 { 1071 RTPrintf("Failed to start the HGCM service.\n"); 1072 return 1; 1073 } 1074 if (RT_FAILURE(testSetPropsHost(&svcTable))) 1075 return 1; 1076 if (RT_FAILURE(testEnumPropsHost(&svcTable))) 1077 return 1; 1078 /* Set up the asynchronous notification test */ 1079 if (RT_FAILURE(setupAsyncNotification(&svcTable))) 1080 return 1; 1081 if (RT_FAILURE(testSetProp(&svcTable))) 1082 return 1; 1083 RTPrintf("Checking the data returned by the asynchronous notification call.\n"); 1084 /* Our previous notification call should have completed by now. */ 1085 if (RT_FAILURE(testAsyncNotification(&svcTable))) 1086 return 1; 1087 if (RT_FAILURE(testDelProp(&svcTable))) 1088 return 1; 1089 if (RT_FAILURE(testGetProp(&svcTable))) 1090 return 1; 1091 if (RT_FAILURE(testGetNotification(&svcTable))) 1092 return 1; 1093 if (RT_FAILURE(svcTable.pfnUnload(svcTable.pvService))) 1094 { 1095 RTPrintf("Failed to unload the HGCM service.\n"); 1096 return 1; 1097 } 1098 if (RT_FAILURE(testSetPropROGuest(&svcTable))) 1099 return 1; 1100 if (RT_FAILURE(testDelPropROGuest(&svcTable))) 1101 return 1; 1060 testConvertFlags(); 1061 test2(); 1062 test3(); 1063 test4(); 1102 1064 1103 1065 return RTTestSummaryAndDestroy(g_hTest);
Note:
See TracChangeset
for help on using the changeset viewer.