Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
tests/fdstreamtest.c | 62 ++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 51 insertions(+), 11 deletions(-)
diff --git a/tests/fdstreamtest.c b/tests/fdstreamtest.c
index f9caebf..5036cec 100644
--- a/tests/fdstreamtest.c
+++ b/tests/fdstreamtest.c
@@ -51,9 +51,11 @@ testFDStreamReadCommon(const char *scratchdir, const unsigned int
flags)
virStreamPtr st = NULL;
size_t i;
virConnectPtr conn = NULL;
+ unsigned long long streamOffset;
bool blocking = !(flags & VIR_STREAM_NONBLOCK);
+ bool sparse = flags & VIR_STREAM_SPARSE;
- virCheckFlags(VIR_STREAM_NONBLOCK, -1);
+ virCheckFlags(VIR_STREAM_NONBLOCK | VIR_STREAM_SPARSE, -1);
if (!(conn = virConnectOpen("test:///default")))
goto cleanup;
@@ -72,6 +74,10 @@ testFDStreamReadCommon(const char *scratchdir, const unsigned int
flags)
goto cleanup;
for (i = 0; i < 10; i++) {
+ if (i && sparse &&
+ lseek(fd, 8192, SEEK_CUR) < 0)
+ goto cleanup;
+
if (safewrite(fd, pattern, PATTERN_LEN) != PATTERN_LEN)
goto cleanup;
}
@@ -82,17 +88,23 @@ testFDStreamReadCommon(const char *scratchdir, const unsigned int
flags)
if (!(st = virStreamNew(conn, flags)))
goto cleanup;
- /* Start reading 1/2 way through first pattern
- * and end 1/2 way through last pattern
+ /* Start reading 1/2 way through first pattern and end 1/2
+ * way through last pattern. In case of sparse file between
+ * each data blocks is one hole.
*/
+ streamOffset = PATTERN_LEN / 2;
if (virFDStreamOpenFile(st, file,
- PATTERN_LEN / 2, PATTERN_LEN * 9,
+ streamOffset,
+ sparse ? PATTERN_LEN * 18 : PATTERN_LEN * 9,
O_RDONLY) < 0)
goto cleanup;
for (i = 0; i < 10; i++) {
size_t offset = 0;
size_t want;
+ bool data = true;
+ unsigned long long oldStreamOffset = streamOffset;
+
if (i == 0)
want = PATTERN_LEN / 2;
else
@@ -101,7 +113,12 @@ testFDStreamReadCommon(const char *scratchdir, const unsigned int
flags)
while (want > 0) {
int got;
reread:
- got = st->driver->streamRecv(st, buf + offset, want);
+ if (sparse)
+ got = st->driver->streamRecvOffset(st, &oldStreamOffset,
+ buf + offset, want);
+ else
+ got = st->driver->streamRecv(st, buf + offset, want);
+
if (got < 0) {
if (got == -2 && !blocking) {
usleep(20 * 1000);
@@ -112,16 +129,33 @@ testFDStreamReadCommon(const char *scratchdir, const unsigned int
flags)
goto cleanup;
}
if (got == 0) {
- /* Expect EOF 1/2 through last pattern */
- if (i == 9 && want == (PATTERN_LEN / 2))
- break;
- virFilePrintf(stderr, "Unexpected EOF block %zu want %zu\n",
- i, want);
- goto cleanup;
+ if (sparse &&
+ oldStreamOffset != streamOffset) {
+ /* oldStreamOffset points to data position. Re-read. */
+ if (data) {
+ virFilePrintf(stderr, "Unexpected hole at offset
%llu\n",
+ streamOffset);
+ }
+ data = !data;
+ streamOffset = oldStreamOffset;
+ goto reread;
+ } else {
+ /* Expect EOF 1/2 through last pattern */
+ if (i == 9 && want == (PATTERN_LEN / 2))
+ break;
+ virFilePrintf(stderr, "Unexpected EOF block %zu want
%zu\n",
+ i, want);
+ goto cleanup;
+ }
}
+ if (i == 0)
+ streamOffset = 8192 + PATTERN_LEN;
+ else
+ streamOffset += 8192 + PATTERN_LEN;
offset += got;
want -= got;
}
+
if (i == 0) {
if (memcmp(buf, pattern + (PATTERN_LEN / 2), PATTERN_LEN / 2) != 0) {
virFilePrintf(stderr, "Mismatched pattern data iteration
%zu\n", i);
@@ -170,6 +204,10 @@ static int testFDStreamReadNonblock(const void *data)
{
return testFDStreamReadCommon(data, VIR_STREAM_NONBLOCK);
}
+static int testFDStreamSparseReadBlock(const void *data)
+{
+ return testFDStreamReadCommon(data, VIR_STREAM_SPARSE);
+}
static int testFDStreamWriteCommon(const char *scratchdir, const unsigned int flags)
@@ -334,6 +372,8 @@ mymain(void)
ret = -1;
if (virtTestRun("Stream write non-blocking ", testFDStreamWriteNonblock,
scratchdir) < 0)
ret = -1;
+ if (virtTestRun("Sparse stream read blocking ",
testFDStreamSparseReadBlock, scratchdir) < 0)
+ ret = -1;
if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
virFileDeleteTree(scratchdir);
--
2.4.10