tstVDSnap.cpp revision e4f367251aede667a6de69baa54ef9eb5f150871
/** @file
*
* Snapshot VBox HDD container test utility.
*/
/*
* Copyright (C) 2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include <iprt/initterm.h>
/**
* A VD snapshot test.
*/
typedef struct VDSNAPTEST
{
/** Backend to use */
const char *pcszBackend;
/** Base image name */
const char *pcszBaseImage;
/** Diff image ending */
const char *pcszDiffSuff;
/** Number of iterations before the test exits */
/** Test pattern size */
/** Minimum number of disk segments */
/** Miaximum number of disk segments */
/** Minimum number of diffs needed before a merge
* operation can occur */
unsigned cDiffsMinBeforeMerge;
/** Chance to get create instead of a merge operation */
/** Chance to change a segment after a diff was created */
/** Numer of allocated blocks in the base image in percent */
/** Merge direction */
bool fForward;
} VDSNAPTEST, *PVDSNAPTEST;
/**
* Structure defining a disk segment.
*/
typedef struct VDDISKSEG
{
/** Start offset in the disk. */
/** Size of the segment. */
/** Pointer to the start of the data in the test pattern used for the segment. */
/** Pointer to the data for a diff write */
} VDDISKSEG, *PVDDISKSEG;
/*******************************************************************************
* Global Variables *
*******************************************************************************/
/** The error count. */
unsigned g_cErrors = 0;
/** Global RNG state. */
{
g_cErrors++;
RTPrintf("\n");
}
{
RTPrintf("tstVD: ");
return VINF_SUCCESS;
}
/**
* Returns true with the given chance in percent.
*
* @returns true or false
* @param iPercentage The percentage of the chance to return true.
*/
static bool tstVDSnapIsTrue(int iPercentage)
{
}
{
for (uint32_t i = 0; i < cDiskSegments; i++)
{
/* Do we want to change the current segment? */
paDiskSeg[i].pbDataDiff = pbTestPattern + RT_ALIGN_64(RTRandAdvU64Ex(g_hRand, 0, cbTestPattern - paDiskSeg[i].cbSeg - 512), 512);
}
}
{
int rc = VINF_SUCCESS;
for (uint32_t i = 0; i < cDiskSegments; i++)
{
{
? paDiskSegments[i].pbData
: paDiskSegments[i].pbDataDiff;
if (pbData)
{
if (RT_FAILURE(rc))
return rc;
}
}
}
return rc;
}
static int tstVDSnapReadVerify(PVBOXHDD pVD, PVDDISKSEG paDiskSegments, uint32_t cDiskSegments, uint64_t cbDisk)
{
int rc = VINF_SUCCESS;
for (uint32_t i = 0; i < cDiskSegments; i++)
{
while (cbRead)
{
if (RT_FAILURE(rc))
return rc;
if (pbCmp)
{
{
{
{
break;
}
}
return VERR_INTERNAL_ERROR;
}
}
else
{
/* Verify that the block is 0 */
{
{
return VERR_INTERNAL_ERROR;
}
}
}
if (pbCmp)
}
}
return rc;
}
{
int rc;
VDGEOMETRY PCHS = { 0, 0, 0 };
VDGEOMETRY LCHS = { 0, 0, 0 };
/** Buffer storing the random test pattern. */
/** Number of disk segments */
/** Array of disk segments */
unsigned cDiffs = 0;
unsigned idDiff = 0; /* Diff ID counter for the filename */
/* Create the virtual disk test data */
for (unsigned i = 0; i < cDiskSegments; i++)
{
paDiskSeg[i].pbData = pbTestPattern + RT_ALIGN_64(RTRandAdvU64Ex(g_hRand, 0, pTest->cbTestPattern - paDiskSeg[i].cbSeg - 512), 512);
else
}
do \
{ \
if (RT_FAILURE(rc)) \
{ \
if (pbTestPattern) \
return rc; \
} \
} while (0)
/* Create error interface. */
/* Create error interface. */
CHECK("VDCreate()");
VD_IMAGE_FLAGS_NONE, "Test image",
CHECK("VDCreateBase()");
bool fInit = true;
uint32_t cIteration = 0;
/* Do the real work now */
while ( RT_SUCCESS(rc)
{
/* Write */
CHECK("tstVDSnapWrite()");
fInit = false;
/* Write returned, do we want to create a new diff or merge them? */
? true
if (fCreate)
{
char *pszDiffFilename = NULL;
CHECK("RTStrAPrintf()");
idDiff++;
cDiffs++;
CHECK("VDCreateDiff()");
/* Change data */
}
else
{
RTPrintf("Merging %u diffs from %u to %u...\n",
else
CHECK("VDMerge()");
/* Go through the disk segments and reset pointers. */
for (uint32_t i = 0; i < cDiskSegments; i++)
{
if (paDiskSeg[i].pbDataDiff)
{
}
}
/* Now compare the result with our test pattern */
CHECK("tstVDSnapReadVerify()");
}
cIteration++;
}
if (pbTestPattern)
for (unsigned i = 0; i < idDiff; i++)
{
char *pszDiffFilename = NULL;
}
return 0;
}
{
RTR3Init();
int rc;
RTPrintf("tstVDSnap: TESTING...\n");
if (RT_FAILURE(rc))
{
return 1;
}
/* Same test with backwards merge */
rc = VDShutdown();
if (RT_FAILURE(rc))
{
g_cErrors++;
}
/*
* Summary
*/
if (!g_cErrors)
RTPrintf("tstVDSnap: SUCCESS\n");
else
return !!g_cErrors;
}