VirtualBox

source: vbox/trunk/src/VBox/Devices/Storage/testcase/tstVD.cpp@ 10390

Last change on this file since 10390 was 9734, checked in by vboxsync, 17 years ago

Extended the interface with backends to support time stamps and parent's filename.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.6 KB
Line 
1/** @file
2 *
3 * Simple VBox HDD container test utility.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#include <VBox/err.h>
23#include <VBox/VBoxHDD-new.h>
24#include <iprt/string.h>
25#include <iprt/stream.h>
26#include <iprt/file.h>
27#include <iprt/mem.h>
28#include <iprt/initterm.h>
29#include <iprt/rand.h>
30#include "stdio.h"
31#include "stdlib.h"
32
33/*******************************************************************************
34* Global Variables *
35*******************************************************************************/
36/** The error count. */
37unsigned g_cErrors = 0;
38
39
40static void tstVDError(void *pvUser, int rc, RT_SRC_POS_DECL,
41 const char *pszFormat, va_list va)
42{
43 g_cErrors++;
44 RTPrintf("tstVD: Error %Vrc at %s:%u (%s): ", rc, RT_SRC_POS_ARGS);
45 RTPrintfV(pszFormat, va);
46 RTPrintf("\n");
47}
48
49
50static int tstVDCreateDelete(const char *pszBackend, const char *pszFilename,
51 uint64_t cbSize, VDIMAGETYPE enmType,
52 unsigned uFlags, bool fDelete)
53{
54 int rc;
55 PVBOXHDD pVD = NULL;
56 PDMMEDIAGEOMETRY PCHS = { 0, 0, 0 };
57 PDMMEDIAGEOMETRY LCHS = { 0, 0, 0 };
58
59#define CHECK(str) \
60 do \
61 { \
62 RTPrintf("%s rc=%Vrc\n", str, rc); \
63 if (VBOX_FAILURE(rc)) \
64 { \
65 VDCloseAll(pVD); \
66 return rc; \
67 } \
68 } while (0)
69
70 rc = VDCreate(tstVDError, NULL, &pVD);
71 CHECK("VDCreate()");
72
73 rc = VDCreateBase(pVD, pszBackend, pszFilename, enmType, cbSize,
74 uFlags, "Test image", &PCHS, &LCHS, VD_OPEN_FLAGS_NORMAL,
75 NULL, NULL);
76 CHECK("VDCreateBase()");
77
78 VDDumpImages(pVD);
79
80 VDClose(pVD, fDelete);
81#undef CHECK
82 return 0;
83}
84
85
86#undef RTDECL
87#define RTDECL(x) static x
88
89/* Start of IPRT code */
90
91/**
92 * The following code is based on the work of George Marsaglia
93 * taken from
94 * http://groups.google.ws/group/comp.sys.sun.admin/msg/7c667186f6cbf354
95 * and
96 * http://groups.google.ws/group/comp.lang.c/msg/0e170777c6e79e8d
97 */
98
99/*
100A C version of a very very good 64-bit RNG is given below.
101You should be able to adapt it to your particular needs.
102
103It is based on the complimentary-multiple-with-carry
104sequence
105 x(n)=a*x(n-4)+carry mod 2^64-1,
106which works as follows:
107Assume a certain multiplier 'a' and a base 'b'.
108Given a current x value and a current carry 'c',
109form: t=a*x+c
110Then the new carry is c=floor(t/b)
111and the new x value is x = b-1-(t mod b).
112
113
114Ordinarily, for 32-bit mwc or cmwc sequences, the
115value t=a*x+c can be formed in 64 bits, then the new c
116is the top and the new x the bottom 32 bits (with a little
117fiddling when b=2^32-1 and cmwc rather than mwc.)
118
119
120To generate 64-bit x's, it is difficult to form
121t=a*x+c in 128 bits then get the new c and new x
122from the the top and bottom halves.
123But if 'a' has a special form, for example,
124a=2^62+2^47+2 and b=2^64-1, then the new c and
125the new x can be formed with shifts, tests and +/-'s,
126again with a little fiddling because b=2^64-1 rather
127than 2^64. (The latter is not an optimal choice because,
128being a square, it cannot be a primitive root of the
129prime a*b^k+1, where 'k' is the 'lag':
130 x(n)=a*x(n-k)+carry mod b.)
131But the multiplier a=2^62+2^47+2 makes a*b^4+1 a prime for
132which b=2^64-1 is a primitive root, and getting the new x and
133new c can be done with arithmetic on integers the size of x.
134*/
135
136struct RndCtx
137{
138 uint64_t x;
139 uint64_t y;
140 uint64_t z;
141 uint64_t w;
142 uint64_t c;
143 uint32_t u32x;
144 uint32_t u32y;
145};
146typedef struct RndCtx RNDCTX;
147typedef RNDCTX *PRNDCTX;
148
149/**
150 * Initialize seeds.
151 *
152 * @remarks You should choose ANY 4 random 64-bit
153 * seeds x,y,z,w < 2^64-1 and a random seed c in
154 * 0<= c < a = 2^62+2^47+2.
155 * There are P=(2^62+2^46+2)*(2^64-1)^4 > 2^318 possible choices
156 * for seeds, the period of the RNG.
157 */
158RTDECL(int) RTPRandInit(PRNDCTX pCtx, uint32_t u32Seed)
159{
160 if (u32Seed == 0)
161 u32Seed = (uint32_t)(ASMReadTSC() >> 8);
162 /* Zero is not a good seed. */
163 if (u32Seed == 0)
164 u32Seed = 362436069;
165 pCtx->x = u32Seed;
166 pCtx->y = 17280675555674358941ULL;
167 pCtx->z = 6376492577913983186ULL;
168 pCtx->w = 9064188857900113776ULL;
169 pCtx->c = 123456789;
170 pCtx->u32x = 2282008;
171 pCtx->u32y = u32Seed;
172 return VINF_SUCCESS;
173}
174
175RTDECL(uint32_t) RTPRandGetSeedInfo(PRNDCTX pCtx)
176{
177 return pCtx->u32y;
178}
179
180/**
181 * Generate a 64-bit unsigned random number.
182 *
183 * @returns The pseudo random number.
184 */
185RTDECL(uint64_t) RTPRandU64(PRNDCTX pCtx)
186{
187 uint64_t t;
188 t = (pCtx->x<<47) + (pCtx->x<<62) + (pCtx->x<<1);
189 t += pCtx->c; t+= (t < pCtx->c);
190 pCtx->c = (t<pCtx->c) + (pCtx->x>>17) + (pCtx->x>>2) + (pCtx->x>>63);
191 pCtx->x = pCtx->y; pCtx->y = pCtx->z ; pCtx->z = pCtx->w;
192 return (pCtx->w = ~(t + pCtx->c)-1);
193}
194
195/**
196 * Generate a 64-bit unsigned pseudo random number in the set
197 * [u64First..u64Last].
198 *
199 * @returns The pseudo random number.
200 * @param u64First First number in the set.
201 * @param u64Last Last number in the set.
202 */
203RTDECL(uint64_t) RTPRandU64Ex(PRNDCTX pCtx, uint64_t u64First, uint64_t u64Last)
204{
205 if (u64First == 0 && u64Last == UINT64_MAX)
206 return RTPRandU64(pCtx);
207
208 uint64_t u64Tmp;
209 uint64_t u64Range = u64Last - u64First + 1;
210 uint64_t u64Scale = UINT64_MAX / u64Range;
211
212 do
213 {
214 u64Tmp = RTPRandU64(pCtx) / u64Scale;
215 } while (u64Tmp >= u64Range);
216 return u64First + u64Tmp;
217}
218
219/**
220 * Generate a 32-bit unsigned random number.
221 *
222 * @returns The pseudo random number.
223 */
224RTDECL(uint32_t) RTPRandU32(PRNDCTX pCtx)
225{
226 return ( pCtx->u32x = 69069 * pCtx->u32x + 123,
227 pCtx->u32y ^= pCtx->u32y<<13,
228 pCtx->u32y ^= pCtx->u32y>>17,
229 pCtx->u32y ^= pCtx->u32y<<5,
230 pCtx->u32x + pCtx->u32y );
231}
232
233/**
234 * Generate a 32-bit unsigned pseudo random number in the set
235 * [u32First..u32Last].
236 *
237 * @returns The pseudo random number.
238 * @param u32First First number in the set.
239 * @param u32Last Last number in the set.
240 */
241RTDECL(uint32_t) RTPRandU32Ex(PRNDCTX pCtx, uint32_t u32First, uint32_t u32Last)
242{
243 if (u32First == 0 && u32Last == UINT32_MAX)
244 return RTPRandU32(pCtx);
245
246 uint32_t u32Tmp;
247 uint32_t u32Range = u32Last - u32First + 1;
248 uint32_t u32Scale = UINT32_MAX / u32Range;
249
250 do
251 {
252 u32Tmp = RTPRandU32(pCtx) / u32Scale;
253 } while (u32Tmp >= u32Range);
254 return u32First + u32Tmp;
255}
256
257/* End of IPRT code */
258
259struct Segment
260{
261 uint64_t u64Offset;
262 uint32_t u32Length;
263 uint32_t u8Value;
264};
265typedef struct Segment *PSEGMENT;
266
267static void initializeRandomGenerator(PRNDCTX pCtx, uint32_t u32Seed)
268{
269 int rc = RTPRandInit(pCtx, u32Seed);
270 if (VBOX_FAILURE(rc))
271 RTPrintf("ERROR: Failed to initialize random generator. RC=%Vrc\n", rc);
272 else
273 {
274 RTPrintf("INFO: Random generator seed used: %x\n", RTPRandGetSeedInfo(pCtx));
275 RTLogPrintf("INFO: Random generator seed used: %x\n", RTPRandGetSeedInfo(pCtx));
276 }
277}
278
279static int compareSegments(const void *left, const void *right)
280{
281 /* Note that no duplicates are allowed in the array being sorted. */
282 return ((PSEGMENT)left)->u64Offset < ((PSEGMENT)right)->u64Offset ? -1 : 1;
283}
284
285static void generateRandomSegments(PRNDCTX pCtx, PSEGMENT pSegment, uint32_t nSegments, uint32_t u32MaxSegmentSize, uint64_t u64DiskSize, uint32_t u32SectorSize, uint8_t u8ValueLow, uint8_t u8ValueHigh)
286{
287 uint32_t i;
288 /* Generate segment offsets. */
289 for (i = 0; i < nSegments; i++)
290 {
291 bool fDuplicateFound;
292 do
293 {
294 pSegment[i].u64Offset = RTPRandU64Ex(pCtx, 0, u64DiskSize / u32SectorSize - 1) * u32SectorSize;
295 fDuplicateFound = false;
296 for (uint32_t j = 0; j < i; j++)
297 if (pSegment[i].u64Offset == pSegment[j].u64Offset)
298 {
299 fDuplicateFound = true;
300 break;
301 }
302 } while (fDuplicateFound);
303 }
304 /* Sort in offset-ascending order. */
305 qsort(pSegment, nSegments, sizeof(*pSegment), compareSegments);
306 /* Put a sentinel at the end. */
307 pSegment[nSegments].u64Offset = u64DiskSize;
308 pSegment[nSegments].u32Length = 0;
309 /* Generate segment lengths and values. */
310 for (i = 0; i < nSegments; i++)
311 {
312 pSegment[i].u32Length = RTPRandU32Ex(pCtx, 1, RT_MIN(pSegment[i+1].u64Offset - pSegment[i].u64Offset,
313 u32MaxSegmentSize) / u32SectorSize) * u32SectorSize;
314 Assert(pSegment[i].u32Length <= u32MaxSegmentSize);
315 pSegment[i].u8Value = RTPRandU32Ex(pCtx, (uint32_t)u8ValueLow, (uint32_t)u8ValueHigh);
316 }
317}
318
319static void mergeSegments(PSEGMENT pBaseSegment, PSEGMENT pDiffSegment, PSEGMENT pMergeSegment, uint32_t u32MaxLength)
320{
321 while (pBaseSegment->u32Length > 0 || pDiffSegment->u32Length > 0)
322 {
323 if (pBaseSegment->u64Offset < pDiffSegment->u64Offset)
324 {
325 *pMergeSegment = *pBaseSegment;
326 if (pMergeSegment->u64Offset + pMergeSegment->u32Length <= pDiffSegment->u64Offset)
327 pBaseSegment++;
328 else
329 {
330 pMergeSegment->u32Length = pDiffSegment->u64Offset - pMergeSegment->u64Offset;
331 Assert(pMergeSegment->u32Length <= u32MaxLength);
332 if (pBaseSegment->u64Offset + pBaseSegment->u32Length >
333 pDiffSegment->u64Offset + pDiffSegment->u32Length)
334 {
335 pBaseSegment->u32Length -= pDiffSegment->u64Offset + pDiffSegment->u32Length - pBaseSegment->u64Offset;
336 Assert(pBaseSegment->u32Length <= u32MaxLength);
337 pBaseSegment->u64Offset = pDiffSegment->u64Offset + pDiffSegment->u32Length;
338 }
339 else
340 pBaseSegment++;
341 }
342 pMergeSegment++;
343 }
344 else
345 {
346 *pMergeSegment = *pDiffSegment;
347 if (pMergeSegment->u64Offset + pMergeSegment->u32Length <= pBaseSegment->u64Offset)
348 {
349 pDiffSegment++;
350 pMergeSegment++;
351 }
352 else
353 {
354 if (pBaseSegment->u64Offset + pBaseSegment->u32Length > pDiffSegment->u64Offset + pDiffSegment->u32Length)
355 {
356 pBaseSegment->u32Length -= pDiffSegment->u64Offset + pDiffSegment->u32Length - pBaseSegment->u64Offset;
357 Assert(pBaseSegment->u32Length <= u32MaxLength);
358 pBaseSegment->u64Offset = pDiffSegment->u64Offset + pDiffSegment->u32Length;
359 pDiffSegment++;
360 pMergeSegment++;
361 }
362 else
363 pBaseSegment++;
364 }
365 }
366 }
367}
368
369static void writeSegmentsToDisk(PVBOXHDD pVD, void *pvBuf, PSEGMENT pSegment)
370{
371 while (pSegment->u32Length)
372 {
373 //memset((uint8_t*)pvBuf + pSegment->u64Offset, pSegment->u8Value, pSegment->u32Length);
374 memset(pvBuf, pSegment->u8Value, pSegment->u32Length);
375 VDWrite(pVD, pSegment->u64Offset, pvBuf, pSegment->u32Length);
376 pSegment++;
377 }
378}
379
380static int readAndCompareSegments(PVBOXHDD pVD, void *pvBuf, PSEGMENT pSegment)
381{
382 while (pSegment->u32Length)
383 {
384 int rc = VDRead(pVD, pSegment->u64Offset, pvBuf, pSegment->u32Length);
385 if (VBOX_FAILURE(rc))
386 {
387 RTPrintf("ERROR: Failed to read from virtual disk\n");
388 return rc;
389 }
390 else
391 {
392 for (unsigned i = 0; i < pSegment->u32Length; i++)
393 if (((uint8_t*)pvBuf)[i] != pSegment->u8Value)
394 {
395 RTPrintf("ERROR: Segment at %Lx of %x bytes is corrupt at offset %x (found %x instead of %x)\n",
396 pSegment->u64Offset, pSegment->u32Length, i, ((uint8_t*)pvBuf)[i],
397 pSegment->u8Value);
398 RTLogPrintf("ERROR: Segment at %Lx of %x bytes is corrupt at offset %x (found %x instead of %x)\n",
399 pSegment->u64Offset, pSegment->u32Length, i, ((uint8_t*)pvBuf)[i],
400 pSegment->u8Value);
401 return VERR_INTERNAL_ERROR;
402 }
403 }
404 pSegment++;
405 }
406
407 return VINF_SUCCESS;
408}
409
410static int tstVDOpenCreateWriteMerge(const char *pszBackend,
411 const char *pszBaseFilename,
412 const char *pszDiffFilename,
413 uint32_t u32Seed)
414{
415 int rc;
416 PVBOXHDD pVD = NULL;
417 char *pszFormat;
418 PDMMEDIAGEOMETRY PCHS = { 0, 0, 0 };
419 PDMMEDIAGEOMETRY LCHS = { 0, 0, 0 };
420 uint64_t u64DiskSize = 1000 * _1M;
421 uint32_t u32SectorSize = 512;
422
423#define CHECK(str) \
424 do \
425 { \
426 RTPrintf("%s rc=%Vrc\n", str, rc); \
427 if (VBOX_FAILURE(rc)) \
428 { \
429 VDCloseAll(pVD); \
430 return rc; \
431 } \
432 } while (0)
433
434 rc = VDCreate(tstVDError, NULL, &pVD);
435 CHECK("VDCreate()");
436
437 RTFILE File;
438 rc = RTFileOpen(&File, pszBaseFilename, RTFILE_O_READ);
439 if (VBOX_SUCCESS(rc))
440 {
441 RTFileClose(File);
442 rc = VDGetFormat(pszBaseFilename, &pszFormat);
443 RTPrintf("VDGetFormat() pszFormat=%s rc=%Vrc\n", pszFormat, rc);
444 if (VBOX_SUCCESS(rc) && strcmp(pszFormat, pszBackend))
445 {
446 rc = VERR_GENERAL_FAILURE;
447 RTPrintf("VDGetFormat() returned incorrect backend name\n");
448 }
449 RTStrFree(pszFormat);
450 CHECK("VDGetFormat()");
451
452 rc = VDOpen(pVD, pszBackend, pszBaseFilename, VD_OPEN_FLAGS_NORMAL);
453 CHECK("VDOpen()");
454 }
455 else
456 {
457 rc = VDCreateBase(pVD, pszBackend, pszBaseFilename,
458 VD_IMAGE_TYPE_NORMAL, u64DiskSize,
459 VD_IMAGE_FLAGS_NONE, "Test image",
460 &PCHS, &LCHS, VD_OPEN_FLAGS_NORMAL,
461 NULL, NULL);
462 CHECK("VDCreateBase()");
463 }
464
465 int nSegments = 100;
466 /* Allocate one extra element for a sentinel. */
467 PSEGMENT paBaseSegments = (PSEGMENT)RTMemAllocZ(sizeof(struct Segment) * (nSegments + 1));
468 PSEGMENT paDiffSegments = (PSEGMENT)RTMemAllocZ(sizeof(struct Segment) * (nSegments + 1));
469 PSEGMENT paMergeSegments = (PSEGMENT)RTMemAllocZ(sizeof(struct Segment) * (nSegments + 1) * 3);
470
471 void *pvBuf = RTMemAlloc(_1M);
472
473 RNDCTX ctx;
474 initializeRandomGenerator(&ctx, u32Seed);
475 generateRandomSegments(&ctx, paBaseSegments, nSegments, _1M, u64DiskSize, u32SectorSize, 0u, 127u);
476 generateRandomSegments(&ctx, paDiffSegments, nSegments, _1M, u64DiskSize, u32SectorSize, 128u, 255u);
477
478 /*PSEGMENT pSegment;
479 RTPrintf("Base segments:\n");
480 for (pSegment = paBaseSegments; pSegment->u32Length; pSegment++)
481 RTPrintf("off: %08Lx len: %05x val: %02x\n", pSegment->u64Offset, pSegment->u32Length, pSegment->u8Value);*/
482 writeSegmentsToDisk(pVD, pvBuf, paBaseSegments);
483
484 rc = VDCreateDiff(pVD, pszBackend, pszDiffFilename,
485 VD_IMAGE_FLAGS_NONE, "Test diff image",
486 VD_OPEN_FLAGS_NORMAL, NULL, NULL);
487 CHECK("VDCreateDiff()");
488
489 /*RTPrintf("\nDiff segments:\n");
490 for (pSegment = paDiffSegments; pSegment->u32Length; pSegment++)
491 RTPrintf("off: %08Lx len: %05x val: %02x\n", pSegment->u64Offset, pSegment->u32Length, pSegment->u8Value);*/
492 writeSegmentsToDisk(pVD, pvBuf, paDiffSegments);
493
494 VDDumpImages(pVD);
495
496 RTPrintf("Merging diff into base..\n");
497 rc = VDMerge(pVD, (unsigned)-1, 0, NULL, NULL);
498 CHECK("VDMerge()");
499
500 mergeSegments(paBaseSegments, paDiffSegments, paMergeSegments, _1M);
501 /*RTPrintf("\nMerged segments:\n");
502 for (pSegment = paMergeSegments; pSegment->u32Length; pSegment++)
503 RTPrintf("off: %08Lx len: %05x val: %02x\n", pSegment->u64Offset, pSegment->u32Length, pSegment->u8Value);*/
504 rc = readAndCompareSegments(pVD, pvBuf, paMergeSegments);
505 CHECK("readAndCompareSegments()");
506
507 RTMemFree(paMergeSegments);
508 RTMemFree(paDiffSegments);
509 RTMemFree(paBaseSegments);
510
511 VDDumpImages(pVD);
512
513 VDCloseAll(pVD);
514#undef CHECK
515 return 0;
516}
517
518static int tstVDCreateWriteOpenRead(const char *pszBackend,
519 const char *pszFilename,
520 uint32_t u32Seed)
521{
522 int rc;
523 PVBOXHDD pVD = NULL;
524 PDMMEDIAGEOMETRY PCHS = { 0, 0, 0 };
525 PDMMEDIAGEOMETRY LCHS = { 0, 0, 0 };
526 uint64_t u64DiskSize = 1000 * _1M;
527 uint32_t u32SectorSize = 512;
528
529#define CHECK(str) \
530 do \
531 { \
532 RTPrintf("%s rc=%Vrc\n", str, rc); \
533 if (VBOX_FAILURE(rc)) \
534 { \
535 VDCloseAll(pVD); \
536 return rc; \
537 } \
538 } while (0)
539
540 rc = VDCreate(tstVDError, NULL, &pVD);
541 CHECK("VDCreate()");
542
543 RTFILE File;
544 rc = RTFileOpen(&File, pszFilename, RTFILE_O_READ);
545 if (VBOX_SUCCESS(rc))
546 {
547 RTFileClose(File);
548 RTFileDelete(pszFilename);
549 }
550
551 rc = VDCreateBase(pVD, pszBackend, pszFilename,
552 VD_IMAGE_TYPE_NORMAL, u64DiskSize,
553 VD_IMAGE_FLAGS_NONE, "Test image",
554 &PCHS, &LCHS, VD_OPEN_FLAGS_NORMAL,
555 NULL, NULL);
556 CHECK("VDCreateBase()");
557
558 int nSegments = 100;
559 /* Allocate one extra element for a sentinel. */
560 PSEGMENT paSegments = (PSEGMENT)RTMemAllocZ(sizeof(struct Segment) * (nSegments + 1));
561
562 void *pvBuf = RTMemAlloc(_1M);
563
564 RNDCTX ctx;
565 initializeRandomGenerator(&ctx, u32Seed);
566 generateRandomSegments(&ctx, paSegments, nSegments, _1M, u64DiskSize, u32SectorSize, 0u, 127u);
567 /*for (PSEGMENT pSegment = paSegments; pSegment->u32Length; pSegment++)
568 RTPrintf("off: %08Lx len: %05x val: %02x\n", pSegment->u64Offset, pSegment->u32Length, pSegment->u8Value);*/
569
570 writeSegmentsToDisk(pVD, pvBuf, paSegments);
571
572 VDCloseAll(pVD);
573
574 rc = VDOpen(pVD, pszBackend, pszFilename, VD_OPEN_FLAGS_NORMAL);
575 CHECK("VDOpen()");
576 rc = readAndCompareSegments(pVD, pvBuf, paSegments);
577 CHECK("readAndCompareSegments()");
578
579 RTMemFree(paSegments);
580
581 VDCloseAll(pVD);
582#undef CHECK
583 return 0;
584}
585
586
587int main(int argc, char *argv[])
588{
589 int rc;
590
591 uint32_t u32Seed = 0; // Means choose random
592
593 if (argc > 1)
594 if (sscanf(argv[1], "%x", &u32Seed) != 1)
595 {
596 RTPrintf("ERROR: Invalid parameter %s. Valid usage is %s <32-bit seed>.\n",
597 argv[1], argv[0]);
598 return 1;
599 }
600
601 RTR3Init();
602 RTPrintf("tstVD: TESTING...\n");
603
604 /*
605 * Clean up potential leftovers from previous unsuccessful runs.
606 */
607 RTFileDelete("tmpVDCreate.vdi");
608 RTFileDelete("tmpVDCreate.vmdk");
609 RTFileDelete("tmpVDCreate.vhd");
610 RTFileDelete("tmpVDBase.vdi");
611 RTFileDelete("tmpVDDiff.vdi");
612 RTFileDelete("tmpVDBase.vmdk");
613 RTFileDelete("tmpVDDiff.vmdk");
614 RTFileDelete("tmpVDBase.vhd");
615 RTFileDelete("tmpVDDiff.vhd");
616#if 1
617 rc = tstVDCreateDelete("VDI", "tmpVDCreate.vdi", 2 * _4G,
618 VD_IMAGE_TYPE_NORMAL, VD_IMAGE_FLAGS_NONE,
619 true);
620 if (VBOX_FAILURE(rc))
621 {
622 RTPrintf("tstVD: dynamic VDI create test failed! rc=%Vrc\n", rc);
623 g_cErrors++;
624 }
625 rc = tstVDCreateDelete("VDI", "tmpVDCreate.vdi", 2 * _4G,
626 VD_IMAGE_TYPE_FIXED, VD_IMAGE_FLAGS_NONE,
627 true);
628 if (VBOX_FAILURE(rc))
629 {
630 RTPrintf("tstVD: fixed VDI create test failed! rc=%Vrc\n", rc);
631 g_cErrors++;
632 }
633 rc = tstVDCreateDelete("VMDK", "tmpVDCreate.vmdk", 2 * _4G,
634 VD_IMAGE_TYPE_NORMAL, VD_IMAGE_FLAGS_NONE,
635 true);
636 if (VBOX_FAILURE(rc))
637 {
638 RTPrintf("tstVD: dynamic VMDK create test failed! rc=%Vrc\n", rc);
639 g_cErrors++;
640 }
641 rc = tstVDCreateDelete("VMDK", "tmpVDCreate.vmdk", 2 * _4G,
642 VD_IMAGE_TYPE_NORMAL, VD_VMDK_IMAGE_FLAGS_SPLIT_2G,
643 true);
644 if (VBOX_FAILURE(rc))
645 {
646 RTPrintf("tstVD: dynamic split VMDK create test failed! rc=%Vrc\n", rc);
647 g_cErrors++;
648 }
649 rc = tstVDCreateDelete("VMDK", "tmpVDCreate.vmdk", 2 * _4G,
650 VD_IMAGE_TYPE_FIXED, VD_IMAGE_FLAGS_NONE,
651 true);
652 if (VBOX_FAILURE(rc))
653 {
654 RTPrintf("tstVD: fixed VMDK create test failed! rc=%Vrc\n", rc);
655 g_cErrors++;
656 }
657 rc = tstVDCreateDelete("VMDK", "tmpVDCreate.vmdk", 2 * _4G,
658 VD_IMAGE_TYPE_FIXED, VD_VMDK_IMAGE_FLAGS_SPLIT_2G,
659 true);
660 if (VBOX_FAILURE(rc))
661 {
662 RTPrintf("tstVD: fixed split VMDK create test failed! rc=%Vrc\n", rc);
663 g_cErrors++;
664 }
665 rc = tstVDCreateDelete("VHD", "tmpVDCreate.vhd", 2 * _4G,
666 VD_IMAGE_TYPE_NORMAL, VD_IMAGE_FLAGS_NONE,
667 true);
668 if (VBOX_FAILURE(rc))
669 {
670 RTPrintf("tstVD: dynamic VHD create test failed! rc=%Vrc\n", rc);
671 g_cErrors++;
672 }
673 rc = tstVDCreateDelete("VHD", "tmpVDCreate.vhd", 2 * _4G,
674 VD_IMAGE_TYPE_FIXED, VD_IMAGE_FLAGS_NONE,
675 true);
676 if (VBOX_FAILURE(rc))
677 {
678 RTPrintf("tstVD: fixed VHD create test failed! rc=%Vrc\n", rc);
679 g_cErrors++;
680 }
681
682 rc = tstVDOpenCreateWriteMerge("VDI", "tmpVDBase.vdi", "tmpVDDiff.vdi", u32Seed);
683 if (VBOX_FAILURE(rc))
684 {
685 RTPrintf("tstVD: VDI test failed (new image)! rc=%Vrc\n", rc);
686 g_cErrors++;
687 }
688 rc = tstVDOpenCreateWriteMerge("VDI", "tmpVDBase.vdi", "tmpVDDiff.vdi", u32Seed);
689 if (VBOX_FAILURE(rc))
690 {
691 RTPrintf("tstVD: VDI test failed (existing image)! rc=%Vrc\n", rc);
692 g_cErrors++;
693 }
694 rc = tstVDOpenCreateWriteMerge("VMDK", "tmpVDBase.vmdk", "tmpVDDiff.vmdk", u32Seed);
695 if (VBOX_FAILURE(rc))
696 {
697 RTPrintf("tstVD: VMDK test failed (new image)! rc=%Vrc\n", rc);
698 g_cErrors++;
699 }
700 rc = tstVDOpenCreateWriteMerge("VMDK", "tmpVDBase.vmdk", "tmpVDDiff.vmdk", u32Seed);
701 if (VBOX_FAILURE(rc))
702 {
703 RTPrintf("tstVD: VMDK test failed (existing image)! rc=%Vrc\n", rc);
704 g_cErrors++;
705 }
706#endif
707
708 rc = tstVDCreateWriteOpenRead("VHD", "tmpVDCreate.vhd", u32Seed);
709 if (VBOX_FAILURE(rc))
710 {
711 RTPrintf("tstVD: VHD test failed (creating image)! rc=%Vrc\n", rc);
712 g_cErrors++;
713 }
714
715 rc = tstVDOpenCreateWriteMerge("VHD", "tmpVDBase.vhd", "tmpVDDiff.vhd", u32Seed);
716 if (VBOX_FAILURE(rc))
717 {
718 RTPrintf("tstVD: VHD test failed (existing image)! rc=%Vrc\n", rc);
719 g_cErrors++;
720 }
721
722 /*
723 * Clean up any leftovers.
724 */
725 RTFileDelete("tmpVDCreate.vdi");
726 RTFileDelete("tmpVDCreate.vmdk");
727 RTFileDelete("tmpVDCreate.vhd");
728 RTFileDelete("tmpVDBase.vdi");
729 RTFileDelete("tmpVDDiff.vdi");
730 RTFileDelete("tmpVDBase.vmdk");
731 RTFileDelete("tmpVDDiff.vmdk");
732 RTFileDelete("tmpVDBase.vhd");
733 RTFileDelete("tmpVDDiff.vhd");
734
735 /*
736 * Summary
737 */
738 if (!g_cErrors)
739 RTPrintf("tstVD: SUCCESS\n");
740 else
741 RTPrintf("tstVD: FAILURE - %d errors\n", g_cErrors);
742
743 return !!g_cErrors;
744}
745
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette