Changeset 31193 in vbox
- Timestamp:
- Jul 29, 2010 8:06:22 AM (14 years ago)
- Location:
- trunk/src/VBox/Devices/Storage/testcase
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/testcase/Makefile.kmk
r28800 r31193 5 5 6 6 # 7 # Copyright (C) 2006-20 07Oracle Corporation7 # Copyright (C) 2006-2010 Oracle Corporation 8 8 # 9 9 # This file is part of VirtualBox Open Source Edition (OSE), as … … 49 49 # 50 50 ifdef VBOX_WITH_TESTCASES 51 PROGRAMS += tstVD tstVD-2 tstVDCopy tstVDSnap 51 PROGRAMS += tstVD tstVD-2 tstVDCopy tstVDSnap tstVDShareable 52 52 ifeq ($(KBUILD_TARGET),l4) 53 53 tstVD_TEMPLATE = VBOXLNXHOSTR3EXE … … 55 55 tstVDCopy_TEMPLATE = VBOXLNXHOSTR3EXE 56 56 tstVDSnap_TEMPLATE = VBOXLNXHOSTR3EXE 57 tstVDShareable_TEMPLATE = VBOXLNXHOSTR3EXE 57 58 else 58 59 tstVD_TEMPLATE = VBOXR3TSTEXE … … 60 61 tstVDCopy_TEMPLATE = VBOXR3TSTEXE 61 62 tstVDSnap_TEMPLATE = VBOXR3TSTEXE 63 tstVDShareable_TEMPLATE = VBOXR3TSTEXE 62 64 endif 63 65 tstVD_LIBS = $(LIB_DDU) $(LIB_RUNTIME) … … 65 67 tstVDCopy_LIBS = $(LIB_DDU) $(LIB_RUNTIME) 66 68 tstVDSnap_LIBS = $(LIB_DDU) $(LIB_RUNTIME) 69 tstVDShareable_LIBS = $(LIB_DDU) $(LIB_RUNTIME) 67 70 tstVD_SOURCES = tstVD.cpp 68 71 tstVD-2_SOURCES = tstVD-2.cpp 69 72 tstVDCopy_SOURCES = tstVDCopy.cpp 70 73 tstVDSnap_SOURCES = tstVDSnap.cpp 74 tstVDShareable_SOURCES = tstVDShareable.cpp 71 75 endif 72 76 -
trunk/src/VBox/Devices/Storage/testcase/tstVDShareable.cpp
r31182 r31193 1 1 /* $Id$ */ 2 2 /** @file 3 * Simple VBox HDD container test utility .3 * Simple VBox HDD container test utility for shareable images. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 20 06-2007Oracle Corporation7 * Copyright (C) 2010 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 64 64 } 65 65 66 static int tstVDCreate Delete(const char *pszBackend, const char *pszFilename,67 uint64_t cbSize, unsigned uFlags, bool fDelete)66 static int tstVDCreateShareDelete(const char *pszBackend, const char *pszFilename, 67 uint64_t cbSize, unsigned uFlags) 68 68 { 69 69 int rc; 70 PVBOXHDD pVD = NULL ;70 PVBOXHDD pVD = NULL, pVD2 = NULL; 71 71 PDMMEDIAGEOMETRY PCHS = { 0, 0, 0 }; 72 72 PDMMEDIAGEOMETRY LCHS = { 0, 0, 0 }; … … 98 98 rc = VDCreate(&VDIError, &pVD); 99 99 CHECK("VDCreate()"); 100 rc = VDCreate(&VDIError, &pVD2); 101 CHECK("VDCreate() #2"); 100 102 101 103 rc = VDCreateBase(pVD, pszBackend, pszFilename, cbSize, … … 104 106 CHECK("VDCreateBase()"); 105 107 106 VD DumpImages(pVD);108 VDClose(pVD, false); 107 109 108 VDClose(pVD, fDelete); 109 if (fDelete) 110 { 111 RTFILE File; 112 rc = RTFileOpen(&File, pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); 113 if (RT_SUCCESS(rc)) 114 { 115 RTFileClose(File); 116 return VERR_INTERNAL_ERROR; 117 } 118 } 110 rc = VDOpen(pVD, pszBackend, pszFilename, VD_OPEN_FLAGS_SHAREABLE, NULL); 111 CHECK("VDOpen()"); 112 rc = VDOpen(pVD2, pszBackend, pszFilename, VD_OPEN_FLAGS_SHAREABLE, NULL); 113 CHECK("VDOpen() #2"); 114 if (VDIsReadOnly(pVD2)) 115 rc = VERR_VD_IMAGE_READ_ONLY; 116 117 VDClose(pVD2, false); 118 VDClose(pVD, true); 119 119 120 120 VDDestroy(pVD); 121 VDDestroy(pVD2); 121 122 #undef CHECK 122 123 return 0; 123 }124 125 static int tstVDOpenDelete(const char *pszBackend, const char *pszFilename)126 {127 int rc;128 PVBOXHDD pVD = NULL;129 PDMMEDIAGEOMETRY PCHS = { 0, 0, 0 };130 PDMMEDIAGEOMETRY LCHS = { 0, 0, 0 };131 PVDINTERFACE pVDIfs = NULL;132 VDINTERFACE VDIError;133 VDINTERFACEERROR VDIErrorCallbacks;134 135 #define CHECK(str) \136 do \137 { \138 RTPrintf("%s rc=%Rrc\n", str, rc); \139 if (RT_FAILURE(rc)) \140 { \141 VDDestroy(pVD); \142 return rc; \143 } \144 } while (0)145 146 /* Create error interface. */147 VDIErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR);148 VDIErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;149 VDIErrorCallbacks.pfnError = tstVDError;150 VDIErrorCallbacks.pfnMessage = tstVDMessage;151 152 rc = VDInterfaceAdd(&VDIError, "tstVD_Error", VDINTERFACETYPE_ERROR, &VDIErrorCallbacks,153 NULL, &pVDIfs);154 AssertRC(rc);155 156 rc = VDCreate(&VDIError, &pVD);157 CHECK("VDCreate()");158 159 rc = VDOpen(pVD, pszBackend, pszFilename, VD_OPEN_FLAGS_NORMAL, NULL);160 CHECK("VDOpen()");161 162 VDDumpImages(pVD);163 164 VDClose(pVD, true);165 RTFILE File;166 rc = RTFileOpen(&File, pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);167 if (RT_SUCCESS(rc))168 {169 RTFileClose(File);170 return VERR_INTERNAL_ERROR;171 }172 173 VDDestroy(pVD);174 #undef CHECK175 return 0;176 }177 178 179 #undef RTDECL180 #define RTDECL(x) static x181 182 /* Start of IPRT code */183 184 /**185 * The following code is based on the work of George Marsaglia186 * taken from187 * http://groups.google.ws/group/comp.sys.sun.admin/msg/7c667186f6cbf354188 * and189 * http://groups.google.ws/group/comp.lang.c/msg/0e170777c6e79e8d190 */191 192 /*193 A C version of a very very good 64-bit RNG is given below.194 You should be able to adapt it to your particular needs.195 196 It is based on the complimentary-multiple-with-carry197 sequence198 x(n)=a*x(n-4)+carry mod 2^64-1,199 which works as follows:200 Assume a certain multiplier 'a' and a base 'b'.201 Given a current x value and a current carry 'c',202 form: t=a*x+c203 Then the new carry is c=floor(t/b)204 and the new x value is x = b-1-(t mod b).205 206 207 Ordinarily, for 32-bit mwc or cmwc sequences, the208 value t=a*x+c can be formed in 64 bits, then the new c209 is the top and the new x the bottom 32 bits (with a little210 fiddling when b=2^32-1 and cmwc rather than mwc.)211 212 213 To generate 64-bit x's, it is difficult to form214 t=a*x+c in 128 bits then get the new c and new x215 from the top and bottom halves.216 But if 'a' has a special form, for example,217 a=2^62+2^47+2 and b=2^64-1, then the new c and218 the new x can be formed with shifts, tests and +/-'s,219 again with a little fiddling because b=2^64-1 rather220 than 2^64. (The latter is not an optimal choice because,221 being a square, it cannot be a primitive root of the222 prime a*b^k+1, where 'k' is the 'lag':223 x(n)=a*x(n-k)+carry mod b.)224 But the multiplier a=2^62+2^47+2 makes a*b^4+1 a prime for225 which b=2^64-1 is a primitive root, and getting the new x and226 new c can be done with arithmetic on integers the size of x.227 */228 229 struct RndCtx230 {231 uint64_t x;232 uint64_t y;233 uint64_t z;234 uint64_t w;235 uint64_t c;236 uint32_t u32x;237 uint32_t u32y;238 };239 typedef struct RndCtx RNDCTX;240 typedef RNDCTX *PRNDCTX;241 242 /**243 * Initialize seeds.244 *245 * @remarks You should choose ANY 4 random 64-bit246 * seeds x,y,z,w < 2^64-1 and a random seed c in247 * 0<= c < a = 2^62+2^47+2.248 * There are P=(2^62+2^46+2)*(2^64-1)^4 > 2^318 possible choices249 * for seeds, the period of the RNG.250 */251 RTDECL(int) RTPRandInit(PRNDCTX pCtx, uint32_t u32Seed)252 {253 if (u32Seed == 0)254 u32Seed = (uint32_t)(ASMReadTSC() >> 8);255 /* Zero is not a good seed. */256 if (u32Seed == 0)257 u32Seed = 362436069;258 pCtx->x = u32Seed;259 pCtx->y = 17280675555674358941ULL;260 pCtx->z = 6376492577913983186ULL;261 pCtx->w = 9064188857900113776ULL;262 pCtx->c = 123456789;263 pCtx->u32x = 2282008;264 pCtx->u32y = u32Seed;265 return VINF_SUCCESS;266 }267 268 RTDECL(uint32_t) RTPRandGetSeedInfo(PRNDCTX pCtx)269 {270 return pCtx->u32y;271 }272 273 /**274 * Generate a 64-bit unsigned random number.275 *276 * @returns The pseudo random number.277 */278 RTDECL(uint64_t) RTPRandU64(PRNDCTX pCtx)279 {280 uint64_t t;281 t = (pCtx->x<<47) + (pCtx->x<<62) + (pCtx->x<<1);282 t += pCtx->c; t+= (t < pCtx->c);283 pCtx->c = (t<pCtx->c) + (pCtx->x>>17) + (pCtx->x>>2) + (pCtx->x>>63);284 pCtx->x = pCtx->y; pCtx->y = pCtx->z ; pCtx->z = pCtx->w;285 return (pCtx->w = ~(t + pCtx->c)-1);286 }287 288 /**289 * Generate a 64-bit unsigned pseudo random number in the set290 * [u64First..u64Last].291 *292 * @returns The pseudo random number.293 * @param u64First First number in the set.294 * @param u64Last Last number in the set.295 */296 RTDECL(uint64_t) RTPRandU64Ex(PRNDCTX pCtx, uint64_t u64First, uint64_t u64Last)297 {298 if (u64First == 0 && u64Last == UINT64_MAX)299 return RTPRandU64(pCtx);300 301 uint64_t u64Tmp;302 uint64_t u64Range = u64Last - u64First + 1;303 uint64_t u64Scale = UINT64_MAX / u64Range;304 305 do306 {307 u64Tmp = RTPRandU64(pCtx) / u64Scale;308 } while (u64Tmp >= u64Range);309 return u64First + u64Tmp;310 }311 312 /**313 * Generate a 32-bit unsigned random number.314 *315 * @returns The pseudo random number.316 */317 RTDECL(uint32_t) RTPRandU32(PRNDCTX pCtx)318 {319 return ( pCtx->u32x = 69069 * pCtx->u32x + 123,320 pCtx->u32y ^= pCtx->u32y<<13,321 pCtx->u32y ^= pCtx->u32y>>17,322 pCtx->u32y ^= pCtx->u32y<<5,323 pCtx->u32x + pCtx->u32y );324 }325 326 /**327 * Generate a 32-bit unsigned pseudo random number in the set328 * [u32First..u32Last].329 *330 * @returns The pseudo random number.331 * @param u32First First number in the set.332 * @param u32Last Last number in the set.333 */334 RTDECL(uint32_t) RTPRandU32Ex(PRNDCTX pCtx, uint32_t u32First, uint32_t u32Last)335 {336 if (u32First == 0 && u32Last == UINT32_MAX)337 return RTPRandU32(pCtx);338 339 uint32_t u32Tmp;340 uint32_t u32Range = u32Last - u32First + 1;341 uint32_t u32Scale = UINT32_MAX / u32Range;342 343 do344 {345 u32Tmp = RTPRandU32(pCtx) / u32Scale;346 } while (u32Tmp >= u32Range);347 return u32First + u32Tmp;348 }349 350 /* End of IPRT code */351 352 struct Segment353 {354 uint64_t u64Offset;355 uint32_t u32Length;356 uint32_t u8Value;357 };358 typedef struct Segment *PSEGMENT;359 360 static void initializeRandomGenerator(PRNDCTX pCtx, uint32_t u32Seed)361 {362 int rc = RTPRandInit(pCtx, u32Seed);363 if (RT_FAILURE(rc))364 RTPrintf("ERROR: Failed to initialize random generator. RC=%Rrc\n", rc);365 else366 {367 RTPrintf("INFO: Random generator seed used: %x\n", RTPRandGetSeedInfo(pCtx));368 RTLogPrintf("INFO: Random generator seed used: %x\n", RTPRandGetSeedInfo(pCtx));369 }370 }371 372 static int compareSegments(const void *left, const void *right)373 {374 /* Note that no duplicates are allowed in the array being sorted. */375 return ((PSEGMENT)left)->u64Offset < ((PSEGMENT)right)->u64Offset ? -1 : 1;376 }377 378 static void generateRandomSegments(PRNDCTX pCtx, PSEGMENT pSegment, uint32_t nSegments, uint32_t u32MaxSegmentSize, uint64_t u64DiskSize, uint32_t u32SectorSize, uint8_t u8ValueLow, uint8_t u8ValueHigh)379 {380 uint32_t i;381 /* Generate segment offsets. */382 for (i = 0; i < nSegments; i++)383 {384 bool fDuplicateFound;385 do386 {387 pSegment[i].u64Offset = RTPRandU64Ex(pCtx, 0, u64DiskSize / u32SectorSize - 1) * u32SectorSize;388 fDuplicateFound = false;389 for (uint32_t j = 0; j < i; j++)390 if (pSegment[i].u64Offset == pSegment[j].u64Offset)391 {392 fDuplicateFound = true;393 break;394 }395 } while (fDuplicateFound);396 }397 /* Sort in offset-ascending order. */398 qsort(pSegment, nSegments, sizeof(*pSegment), compareSegments);399 /* Put a sentinel at the end. */400 pSegment[nSegments].u64Offset = u64DiskSize;401 pSegment[nSegments].u32Length = 0;402 /* Generate segment lengths and values. */403 for (i = 0; i < nSegments; i++)404 {405 pSegment[i].u32Length = RTPRandU32Ex(pCtx, 1, RT_MIN(pSegment[i+1].u64Offset - pSegment[i].u64Offset,406 u32MaxSegmentSize) / u32SectorSize) * u32SectorSize;407 Assert(pSegment[i].u32Length <= u32MaxSegmentSize);408 pSegment[i].u8Value = RTPRandU32Ex(pCtx, (uint32_t)u8ValueLow, (uint32_t)u8ValueHigh);409 }410 }411 412 static void mergeSegments(PSEGMENT pBaseSegment, PSEGMENT pDiffSegment, PSEGMENT pMergeSegment, uint32_t u32MaxLength)413 {414 while (pBaseSegment->u32Length > 0 || pDiffSegment->u32Length > 0)415 {416 if (pBaseSegment->u64Offset < pDiffSegment->u64Offset)417 {418 *pMergeSegment = *pBaseSegment;419 if (pMergeSegment->u64Offset + pMergeSegment->u32Length <= pDiffSegment->u64Offset)420 pBaseSegment++;421 else422 {423 pMergeSegment->u32Length = pDiffSegment->u64Offset - pMergeSegment->u64Offset;424 Assert(pMergeSegment->u32Length <= u32MaxLength);425 if (pBaseSegment->u64Offset + pBaseSegment->u32Length >426 pDiffSegment->u64Offset + pDiffSegment->u32Length)427 {428 pBaseSegment->u32Length -= pDiffSegment->u64Offset + pDiffSegment->u32Length - pBaseSegment->u64Offset;429 Assert(pBaseSegment->u32Length <= u32MaxLength);430 pBaseSegment->u64Offset = pDiffSegment->u64Offset + pDiffSegment->u32Length;431 }432 else433 pBaseSegment++;434 }435 pMergeSegment++;436 }437 else438 {439 *pMergeSegment = *pDiffSegment;440 if (pMergeSegment->u64Offset + pMergeSegment->u32Length <= pBaseSegment->u64Offset)441 {442 pDiffSegment++;443 pMergeSegment++;444 }445 else446 {447 if (pBaseSegment->u64Offset + pBaseSegment->u32Length > pDiffSegment->u64Offset + pDiffSegment->u32Length)448 {449 pBaseSegment->u32Length -= pDiffSegment->u64Offset + pDiffSegment->u32Length - pBaseSegment->u64Offset;450 Assert(pBaseSegment->u32Length <= u32MaxLength);451 pBaseSegment->u64Offset = pDiffSegment->u64Offset + pDiffSegment->u32Length;452 pDiffSegment++;453 pMergeSegment++;454 }455 else456 pBaseSegment++;457 }458 }459 }460 }461 462 static void writeSegmentsToDisk(PVBOXHDD pVD, void *pvBuf, PSEGMENT pSegment)463 {464 while (pSegment->u32Length)465 {466 //memset((uint8_t*)pvBuf + pSegment->u64Offset, pSegment->u8Value, pSegment->u32Length);467 memset(pvBuf, pSegment->u8Value, pSegment->u32Length);468 VDWrite(pVD, pSegment->u64Offset, pvBuf, pSegment->u32Length);469 pSegment++;470 }471 }472 473 static int readAndCompareSegments(PVBOXHDD pVD, void *pvBuf, PSEGMENT pSegment)474 {475 while (pSegment->u32Length)476 {477 int rc = VDRead(pVD, pSegment->u64Offset, pvBuf, pSegment->u32Length);478 if (RT_FAILURE(rc))479 {480 RTPrintf("ERROR: Failed to read from virtual disk\n");481 return rc;482 }483 else484 {485 for (unsigned i = 0; i < pSegment->u32Length; i++)486 if (((uint8_t*)pvBuf)[i] != pSegment->u8Value)487 {488 RTPrintf("ERROR: Segment at %Lx of %x bytes is corrupt at offset %x (found %x instead of %x)\n",489 pSegment->u64Offset, pSegment->u32Length, i, ((uint8_t*)pvBuf)[i],490 pSegment->u8Value);491 RTLogPrintf("ERROR: Segment at %Lx of %x bytes is corrupt at offset %x (found %x instead of %x)\n",492 pSegment->u64Offset, pSegment->u32Length, i, ((uint8_t*)pvBuf)[i],493 pSegment->u8Value);494 return VERR_INTERNAL_ERROR;495 }496 }497 pSegment++;498 }499 500 return VINF_SUCCESS;501 }502 503 static int tstVDOpenCreateWriteMerge(const char *pszBackend,504 const char *pszBaseFilename,505 const char *pszDiffFilename,506 uint32_t u32Seed)507 {508 int rc;509 PVBOXHDD pVD = NULL;510 char *pszFormat;511 PDMMEDIAGEOMETRY PCHS = { 0, 0, 0 };512 PDMMEDIAGEOMETRY LCHS = { 0, 0, 0 };513 uint64_t u64DiskSize = 1000 * _1M;514 uint32_t u32SectorSize = 512;515 PVDINTERFACE pVDIfs = NULL;516 VDINTERFACE VDIError;517 VDINTERFACEERROR VDIErrorCallbacks;518 519 #define CHECK(str) \520 do \521 { \522 RTPrintf("%s rc=%Rrc\n", str, rc); \523 if (RT_FAILURE(rc)) \524 { \525 if (pvBuf) \526 RTMemFree(pvBuf); \527 VDDestroy(pVD); \528 return rc; \529 } \530 } while (0)531 532 void *pvBuf = RTMemAlloc(_1M);533 534 /* Create error interface. */535 VDIErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR);536 VDIErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;537 VDIErrorCallbacks.pfnError = tstVDError;538 VDIErrorCallbacks.pfnMessage = tstVDMessage;539 540 rc = VDInterfaceAdd(&VDIError, "tstVD_Error", VDINTERFACETYPE_ERROR, &VDIErrorCallbacks,541 NULL, &pVDIfs);542 AssertRC(rc);543 544 545 rc = VDCreate(&VDIError, &pVD);546 CHECK("VDCreate()");547 548 RTFILE File;549 rc = RTFileOpen(&File, pszBaseFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);550 if (RT_SUCCESS(rc))551 {552 RTFileClose(File);553 rc = VDGetFormat(NULL, pszBaseFilename, &pszFormat);554 RTPrintf("VDGetFormat() pszFormat=%s rc=%Rrc\n", pszFormat, rc);555 if (RT_SUCCESS(rc) && strcmp(pszFormat, pszBackend))556 {557 rc = VERR_GENERAL_FAILURE;558 RTPrintf("VDGetFormat() returned incorrect backend name\n");559 }560 RTStrFree(pszFormat);561 CHECK("VDGetFormat()");562 563 rc = VDOpen(pVD, pszBackend, pszBaseFilename, VD_OPEN_FLAGS_NORMAL,564 NULL);565 CHECK("VDOpen()");566 }567 else568 {569 rc = VDCreateBase(pVD, pszBackend, pszBaseFilename, u64DiskSize,570 VD_IMAGE_FLAGS_NONE, "Test image",571 &PCHS, &LCHS, NULL, VD_OPEN_FLAGS_NORMAL,572 NULL, NULL);573 CHECK("VDCreateBase()");574 }575 576 int nSegments = 100;577 /* Allocate one extra element for a sentinel. */578 PSEGMENT paBaseSegments = (PSEGMENT)RTMemAllocZ(sizeof(struct Segment) * (nSegments + 1));579 PSEGMENT paDiffSegments = (PSEGMENT)RTMemAllocZ(sizeof(struct Segment) * (nSegments + 1));580 PSEGMENT paMergeSegments = (PSEGMENT)RTMemAllocZ(sizeof(struct Segment) * (nSegments + 1) * 3);581 582 RNDCTX ctx;583 initializeRandomGenerator(&ctx, u32Seed);584 generateRandomSegments(&ctx, paBaseSegments, nSegments, _1M, u64DiskSize, u32SectorSize, 0u, 127u);585 generateRandomSegments(&ctx, paDiffSegments, nSegments, _1M, u64DiskSize, u32SectorSize, 128u, 255u);586 587 /*PSEGMENT pSegment;588 RTPrintf("Base segments:\n");589 for (pSegment = paBaseSegments; pSegment->u32Length; pSegment++)590 RTPrintf("off: %08Lx len: %05x val: %02x\n", pSegment->u64Offset, pSegment->u32Length, pSegment->u8Value);*/591 writeSegmentsToDisk(pVD, pvBuf, paBaseSegments);592 593 rc = VDCreateDiff(pVD, pszBackend, pszDiffFilename,594 VD_IMAGE_FLAGS_NONE, "Test diff image", NULL, NULL,595 VD_OPEN_FLAGS_NORMAL, NULL, NULL);596 CHECK("VDCreateDiff()");597 598 /*RTPrintf("\nDiff segments:\n");599 for (pSegment = paDiffSegments; pSegment->u32Length; pSegment++)600 RTPrintf("off: %08Lx len: %05x val: %02x\n", pSegment->u64Offset, pSegment->u32Length, pSegment->u8Value);*/601 writeSegmentsToDisk(pVD, pvBuf, paDiffSegments);602 603 VDDumpImages(pVD);604 605 RTPrintf("Merging diff into base..\n");606 rc = VDMerge(pVD, VD_LAST_IMAGE, 0, NULL);607 CHECK("VDMerge()");608 609 mergeSegments(paBaseSegments, paDiffSegments, paMergeSegments, _1M);610 /*RTPrintf("\nMerged segments:\n");611 for (pSegment = paMergeSegments; pSegment->u32Length; pSegment++)612 RTPrintf("off: %08Lx len: %05x val: %02x\n", pSegment->u64Offset, pSegment->u32Length, pSegment->u8Value);*/613 rc = readAndCompareSegments(pVD, pvBuf, paMergeSegments);614 CHECK("readAndCompareSegments()");615 616 RTMemFree(paMergeSegments);617 RTMemFree(paDiffSegments);618 RTMemFree(paBaseSegments);619 620 VDDumpImages(pVD);621 622 VDDestroy(pVD);623 if (pvBuf)624 RTMemFree(pvBuf);625 #undef CHECK626 return 0;627 }628 629 static int tstVDCreateWriteOpenRead(const char *pszBackend,630 const char *pszFilename,631 uint32_t u32Seed)632 {633 int rc;634 PVBOXHDD pVD = NULL;635 PDMMEDIAGEOMETRY PCHS = { 0, 0, 0 };636 PDMMEDIAGEOMETRY LCHS = { 0, 0, 0 };637 uint64_t u64DiskSize = 1000 * _1M;638 uint32_t u32SectorSize = 512;639 PVDINTERFACE pVDIfs = NULL;640 VDINTERFACE VDIError;641 VDINTERFACEERROR VDIErrorCallbacks;642 643 #define CHECK(str) \644 do \645 { \646 RTPrintf("%s rc=%Rrc\n", str, rc); \647 if (RT_FAILURE(rc)) \648 { \649 if (pvBuf) \650 RTMemFree(pvBuf); \651 VDDestroy(pVD); \652 return rc; \653 } \654 } while (0)655 656 void *pvBuf = RTMemAlloc(_1M);657 658 /* Create error interface. */659 VDIErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR);660 VDIErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;661 VDIErrorCallbacks.pfnError = tstVDError;662 VDIErrorCallbacks.pfnMessage = tstVDMessage;663 664 rc = VDInterfaceAdd(&VDIError, "tstVD_Error", VDINTERFACETYPE_ERROR, &VDIErrorCallbacks,665 NULL, &pVDIfs);666 AssertRC(rc);667 668 669 rc = VDCreate(&VDIError, &pVD);670 CHECK("VDCreate()");671 672 RTFILE File;673 rc = RTFileOpen(&File, pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);674 if (RT_SUCCESS(rc))675 {676 RTFileClose(File);677 RTFileDelete(pszFilename);678 }679 680 rc = VDCreateBase(pVD, pszBackend, pszFilename, u64DiskSize,681 VD_IMAGE_FLAGS_NONE, "Test image",682 &PCHS, &LCHS, NULL, VD_OPEN_FLAGS_NORMAL,683 NULL, NULL);684 CHECK("VDCreateBase()");685 686 int nSegments = 100;687 /* Allocate one extra element for a sentinel. */688 PSEGMENT paSegments = (PSEGMENT)RTMemAllocZ(sizeof(struct Segment) * (nSegments + 1));689 690 RNDCTX ctx;691 initializeRandomGenerator(&ctx, u32Seed);692 generateRandomSegments(&ctx, paSegments, nSegments, _1M, u64DiskSize, u32SectorSize, 0u, 127u);693 /*for (PSEGMENT pSegment = paSegments; pSegment->u32Length; pSegment++)694 RTPrintf("off: %08Lx len: %05x val: %02x\n", pSegment->u64Offset, pSegment->u32Length, pSegment->u8Value);*/695 696 writeSegmentsToDisk(pVD, pvBuf, paSegments);697 698 VDCloseAll(pVD);699 700 rc = VDOpen(pVD, pszBackend, pszFilename, VD_OPEN_FLAGS_NORMAL, NULL);701 CHECK("VDOpen()");702 rc = readAndCompareSegments(pVD, pvBuf, paSegments);703 CHECK("readAndCompareSegments()");704 705 RTMemFree(paSegments);706 707 VDDestroy(pVD);708 if (pvBuf)709 RTMemFree(pvBuf);710 #undef CHECK711 return 0;712 }713 714 static int tstVmdkRename(const char *src, const char *dst)715 {716 int rc;717 PVBOXHDD pVD = NULL;718 PVDINTERFACE pVDIfs = NULL;719 VDINTERFACE VDIError;720 VDINTERFACEERROR VDIErrorCallbacks;721 722 #define CHECK(str) \723 do \724 { \725 RTPrintf("%s rc=%Rrc\n", str, rc); \726 if (RT_FAILURE(rc)) \727 { \728 VDDestroy(pVD); \729 return rc; \730 } \731 } while (0)732 733 /* Create error interface. */734 VDIErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR);735 VDIErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;736 VDIErrorCallbacks.pfnError = tstVDError;737 VDIErrorCallbacks.pfnMessage = tstVDMessage;738 739 rc = VDInterfaceAdd(&VDIError, "tstVD_Error", VDINTERFACETYPE_ERROR, &VDIErrorCallbacks,740 NULL, &pVDIfs);741 AssertRC(rc);742 743 rc = VDCreate(&VDIError, &pVD);744 CHECK("VDCreate()");745 746 rc = VDOpen(pVD, "VMDK", src, VD_OPEN_FLAGS_NORMAL, NULL);747 CHECK("VDOpen()");748 rc = VDCopy(pVD, 0, pVD, "VMDK", dst, true, 0, VD_IMAGE_FLAGS_NONE, NULL, NULL, NULL, NULL);749 CHECK("VDCopy()");750 751 VDDestroy(pVD);752 #undef CHECK753 return 0;754 }755 756 static int tstVmdkCreateRenameOpen(const char *src, const char *dst,757 uint64_t cbSize, unsigned uFlags)758 {759 int rc = tstVDCreateDelete("VMDK", src, cbSize, uFlags, false);760 if (RT_FAILURE(rc))761 return rc;762 763 rc = tstVmdkRename(src, dst);764 if (RT_FAILURE(rc))765 return rc;766 767 PVBOXHDD pVD = NULL;768 PVDINTERFACE pVDIfs = NULL;769 VDINTERFACE VDIError;770 VDINTERFACEERROR VDIErrorCallbacks;771 772 #define CHECK(str) \773 do \774 { \775 RTPrintf("%s rc=%Rrc\n", str, rc); \776 if (RT_FAILURE(rc)) \777 { \778 VDCloseAll(pVD); \779 return rc; \780 } \781 } while (0)782 783 /* Create error interface. */784 VDIErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR);785 VDIErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;786 VDIErrorCallbacks.pfnError = tstVDError;787 VDIErrorCallbacks.pfnMessage = tstVDMessage;788 789 rc = VDInterfaceAdd(&VDIError, "tstVD_Error", VDINTERFACETYPE_ERROR, &VDIErrorCallbacks,790 NULL, &pVDIfs);791 AssertRC(rc);792 793 rc = VDCreate(&VDIError, &pVD);794 CHECK("VDCreate()");795 796 rc = VDOpen(pVD, "VMDK", dst, VD_OPEN_FLAGS_NORMAL, NULL);797 CHECK("VDOpen()");798 799 VDClose(pVD, true);800 CHECK("VDClose()");801 VDDestroy(pVD);802 #undef CHECK803 return rc;804 }805 806 #if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)807 #define DST_PATH "tmp\\tmpVDRename.vmdk"808 #else809 #define DST_PATH "tmp/tmpVDRename.vmdk"810 #endif811 812 static void tstVmdk()813 {814 int rc = tstVmdkCreateRenameOpen("tmpVDCreate.vmdk", "tmpVDRename.vmdk", _4G,815 VD_IMAGE_FLAGS_NONE);816 if (RT_FAILURE(rc))817 {818 RTPrintf("tstVD: VMDK rename (single extent, embedded descriptor, same dir) test failed! rc=%Rrc\n", rc);819 g_cErrors++;820 }821 rc = tstVmdkCreateRenameOpen("tmpVDCreate.vmdk", "tmpVDRename.vmdk", _4G,822 VD_VMDK_IMAGE_FLAGS_SPLIT_2G);823 if (RT_FAILURE(rc))824 {825 RTPrintf("tstVD: VMDK rename (multiple extent, separate descriptor, same dir) test failed! rc=%Rrc\n", rc);826 g_cErrors++;827 }828 rc = tstVmdkCreateRenameOpen("tmpVDCreate.vmdk", DST_PATH, _4G,829 VD_IMAGE_FLAGS_NONE);830 if (RT_FAILURE(rc))831 {832 RTPrintf("tstVD: VMDK rename (single extent, embedded descriptor, another dir) test failed! rc=%Rrc\n", rc);833 g_cErrors++;834 }835 rc = tstVmdkCreateRenameOpen("tmpVDCreate.vmdk", DST_PATH, _4G,836 VD_VMDK_IMAGE_FLAGS_SPLIT_2G);837 if (RT_FAILURE(rc))838 {839 RTPrintf("tstVD: VMDK rename (multiple extent, separate descriptor, another dir) test failed! rc=%Rrc\n", rc);840 g_cErrors++;841 }842 843 RTFILE File;844 rc = RTFileOpen(&File, DST_PATH, RTFILE_O_WRITE | RTFILE_O_CREATE | RTFILE_O_DENY_NONE);845 if (RT_SUCCESS(rc))846 RTFileClose(File);847 848 rc = tstVmdkCreateRenameOpen("tmpVDCreate.vmdk", DST_PATH, _4G,849 VD_VMDK_IMAGE_FLAGS_SPLIT_2G);850 if (RT_SUCCESS(rc))851 {852 RTPrintf("tstVD: VMDK rename (multiple extent, separate descriptor, another dir, already exists) test failed!\n");853 g_cErrors++;854 }855 RTFileDelete(DST_PATH);856 RTFileDelete("tmpVDCreate.vmdk");857 RTFileDelete("tmpVDCreate-s001.vmdk");858 RTFileDelete("tmpVDCreate-s002.vmdk");859 RTFileDelete("tmpVDCreate-s003.vmdk");860 124 } 861 125 … … 865 129 int rc; 866 130 867 uint32_t u32Seed = 0; // Means choose random868 869 if (argc > 1)870 if (sscanf(argv[1], "%x", &u32Seed) != 1)871 {872 RTPrintf("ERROR: Invalid parameter %s. Valid usage is %s <32-bit seed>.\n",873 argv[1], argv[0]);874 return 1;875 }876 877 131 RTPrintf("tstVD: TESTING...\n"); 878 132 … … 881 135 */ 882 136 RTFileDelete("tmpVDCreate.vdi"); 883 RTFileDelete("tmpVDCreate.vmdk");884 RTFileDelete("tmpVDCreate.vhd");885 RTFileDelete("tmpVDBase.vdi");886 RTFileDelete("tmpVDDiff.vdi");887 RTFileDelete("tmpVDBase.vmdk");888 RTFileDelete("tmpVDDiff.vmdk");889 RTFileDelete("tmpVDBase.vhd");890 RTFileDelete("tmpVDDiff.vhd");891 RTFileDelete("tmpVDCreate-s001.vmdk");892 RTFileDelete("tmpVDCreate-s002.vmdk");893 RTFileDelete("tmpVDCreate-s003.vmdk");894 RTFileDelete("tmpVDRename.vmdk");895 RTFileDelete("tmpVDRename-s001.vmdk");896 RTFileDelete("tmpVDRename-s002.vmdk");897 RTFileDelete("tmpVDRename-s003.vmdk");898 RTFileDelete("tmp/tmpVDRename.vmdk");899 RTFileDelete("tmp/tmpVDRename-s001.vmdk");900 RTFileDelete("tmp/tmpVDRename-s002.vmdk");901 RTFileDelete("tmp/tmpVDRename-s003.vmdk");902 137 903 138 if (!RTDirExists("tmp")) … … 911 146 } 912 147 913 #ifdef V MDK_TEST914 rc = tstVDCreate Delete("VMDK", "tmpVDCreate.vmdk", 2 * _4G,915 VD_IMAGE_FLAGS_NONE, true);148 #ifdef VDI_TEST 149 rc = tstVDCreateShareDelete("VDI", "tmpVDCreate.vdi", 10 * _1M, 150 VD_IMAGE_FLAGS_FIXED); 916 151 if (RT_FAILURE(rc)) 917 152 { 918 RTPrintf("tstVD: dynamic VMDK create test failed! rc=%Rrc\n", rc); 919 g_cErrors++; 920 } 921 rc = tstVDCreateDelete("VMDK", "tmpVDCreate.vmdk", 2 * _4G, 922 VD_IMAGE_FLAGS_NONE, false); 923 if (RT_FAILURE(rc)) 924 { 925 RTPrintf("tstVD: dynamic VMDK create test failed! rc=%Rrc\n", rc); 926 g_cErrors++; 927 } 928 rc = tstVDOpenDelete("VMDK", "tmpVDCreate.vmdk"); 929 if (RT_FAILURE(rc)) 930 { 931 RTPrintf("tstVD: VMDK delete test failed! rc=%Rrc\n", rc); 932 g_cErrors++; 933 } 934 935 tstVmdk(); 936 #endif /* VMDK_TEST */ 937 #ifdef VDI_TEST 938 rc = tstVDCreateDelete("VDI", "tmpVDCreate.vdi", 2 * _4G, 939 VD_IMAGE_FLAGS_NONE, true); 940 if (RT_FAILURE(rc)) 941 { 942 RTPrintf("tstVD: dynamic VDI create test failed! rc=%Rrc\n", rc); 943 g_cErrors++; 944 } 945 rc = tstVDCreateDelete("VDI", "tmpVDCreate.vdi", 2 * _4G, 946 VD_IMAGE_FLAGS_NONE, true); 947 if (RT_FAILURE(rc)) 948 { 949 RTPrintf("tstVD: fixed VDI create test failed! rc=%Rrc\n", rc); 153 RTPrintf("tstVD: VDI shareable test failed! rc=%Rrc\n", rc); 950 154 g_cErrors++; 951 155 } 952 156 #endif /* VDI_TEST */ 953 #ifdef VMDK_TEST954 rc = tstVDCreateDelete("VMDK", "tmpVDCreate.vmdk", 2 * _4G,955 VD_IMAGE_FLAGS_NONE, true);956 if (RT_FAILURE(rc))957 {958 RTPrintf("tstVD: dynamic VMDK create test failed! rc=%Rrc\n", rc);959 g_cErrors++;960 }961 rc = tstVDCreateDelete("VMDK", "tmpVDCreate.vmdk", 2 * _4G,962 VD_VMDK_IMAGE_FLAGS_SPLIT_2G, true);963 if (RT_FAILURE(rc))964 {965 RTPrintf("tstVD: dynamic split VMDK create test failed! rc=%Rrc\n", rc);966 g_cErrors++;967 }968 rc = tstVDCreateDelete("VMDK", "tmpVDCreate.vmdk", 2 * _4G,969 VD_IMAGE_FLAGS_FIXED, true);970 if (RT_FAILURE(rc))971 {972 RTPrintf("tstVD: fixed VMDK create test failed! rc=%Rrc\n", rc);973 g_cErrors++;974 }975 rc = tstVDCreateDelete("VMDK", "tmpVDCreate.vmdk", 2 * _4G,976 VD_IMAGE_FLAGS_FIXED | VD_VMDK_IMAGE_FLAGS_SPLIT_2G,977 true);978 if (RT_FAILURE(rc))979 {980 RTPrintf("tstVD: fixed split VMDK create test failed! rc=%Rrc\n", rc);981 g_cErrors++;982 }983 #endif /* VMDK_TEST */984 #ifdef VHD_TEST985 rc = tstVDCreateDelete("VHD", "tmpVDCreate.vhd", 2 * _4G,986 VD_IMAGE_FLAGS_NONE, true);987 if (RT_FAILURE(rc))988 {989 RTPrintf("tstVD: dynamic VHD create test failed! rc=%Rrc\n", rc);990 g_cErrors++;991 }992 rc = tstVDCreateDelete("VHD", "tmpVDCreate.vhd", 2 * _4G,993 VD_IMAGE_FLAGS_FIXED, true);994 if (RT_FAILURE(rc))995 {996 RTPrintf("tstVD: fixed VHD create test failed! rc=%Rrc\n", rc);997 g_cErrors++;998 }999 #endif /* VHD_TEST */1000 #ifdef VDI_TEST1001 rc = tstVDOpenCreateWriteMerge("VDI", "tmpVDBase.vdi", "tmpVDDiff.vdi", u32Seed);1002 if (RT_FAILURE(rc))1003 {1004 RTPrintf("tstVD: VDI test failed (new image)! rc=%Rrc\n", rc);1005 g_cErrors++;1006 }1007 rc = tstVDOpenCreateWriteMerge("VDI", "tmpVDBase.vdi", "tmpVDDiff.vdi", u32Seed);1008 if (RT_FAILURE(rc))1009 {1010 RTPrintf("tstVD: VDI test failed (existing image)! rc=%Rrc\n", rc);1011 g_cErrors++;1012 }1013 #endif /* VDI_TEST */1014 #ifdef VMDK_TEST1015 rc = tstVDOpenCreateWriteMerge("VMDK", "tmpVDBase.vmdk", "tmpVDDiff.vmdk", u32Seed);1016 if (RT_FAILURE(rc))1017 {1018 RTPrintf("tstVD: VMDK test failed (new image)! rc=%Rrc\n", rc);1019 g_cErrors++;1020 }1021 rc = tstVDOpenCreateWriteMerge("VMDK", "tmpVDBase.vmdk", "tmpVDDiff.vmdk", u32Seed);1022 if (RT_FAILURE(rc))1023 {1024 RTPrintf("tstVD: VMDK test failed (existing image)! rc=%Rrc\n", rc);1025 g_cErrors++;1026 }1027 #endif /* VMDK_TEST */1028 #ifdef VHD_TEST1029 rc = tstVDCreateWriteOpenRead("VHD", "tmpVDCreate.vhd", u32Seed);1030 if (RT_FAILURE(rc))1031 {1032 RTPrintf("tstVD: VHD test failed (creating image)! rc=%Rrc\n", rc);1033 g_cErrors++;1034 }1035 1036 rc = tstVDOpenCreateWriteMerge("VHD", "tmpVDBase.vhd", "tmpVDDiff.vhd", u32Seed);1037 if (RT_FAILURE(rc))1038 {1039 RTPrintf("tstVD: VHD test failed (existing image)! rc=%Rrc\n", rc);1040 g_cErrors++;1041 }1042 #endif /* VHD_TEST */1043 157 1044 158 /* … … 1046 160 */ 1047 161 RTFileDelete("tmpVDCreate.vdi"); 1048 RTFileDelete("tmpVDCreate.vmdk");1049 RTFileDelete("tmpVDCreate.vhd");1050 RTFileDelete("tmpVDBase.vdi");1051 RTFileDelete("tmpVDDiff.vdi");1052 RTFileDelete("tmpVDBase.vmdk");1053 RTFileDelete("tmpVDDiff.vmdk");1054 RTFileDelete("tmpVDBase.vhd");1055 RTFileDelete("tmpVDDiff.vhd");1056 RTFileDelete("tmpVDCreate-s001.vmdk");1057 RTFileDelete("tmpVDCreate-s002.vmdk");1058 RTFileDelete("tmpVDCreate-s003.vmdk");1059 RTFileDelete("tmpVDRename.vmdk");1060 RTFileDelete("tmpVDRename-s001.vmdk");1061 RTFileDelete("tmpVDRename-s002.vmdk");1062 RTFileDelete("tmpVDRename-s003.vmdk");1063 162 1064 163 rc = VDShutdown(); … … 1069 168 } 1070 169 /* 1071 * Summary1072 */170 * Summary 171 */ 1073 172 if (!g_cErrors) 1074 173 RTPrintf("tstVD: SUCCESS\n");
Note:
See TracChangeset
for help on using the changeset viewer.