backup: Wire up qemu full pull backup commands over QMP
[libvirt/ericb.git] / tests / fdstreamtest.c
blob054c405cec6d5968293b20263913f0793d230ea6
1 /*
2 * Copyright (C) 2013 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; If not, see
16 * <http://www.gnu.org/licenses/>.
19 #include <config.h>
21 #include <fcntl.h>
23 #include "testutils.h"
25 #include "virfdstream.h"
26 #include "datatypes.h"
27 #include "virerror.h"
28 #include "viralloc.h"
29 #include "virlog.h"
30 #include "virstring.h"
31 #include "virfile.h"
32 #include "virutil.h"
34 #define VIR_FROM_THIS VIR_FROM_NONE
36 VIR_LOG_INIT("tests.fdstreamtest");
38 #define PATTERN_LEN 256
40 static int testFDStreamReadCommon(const char *scratchdir, bool blocking)
42 int fd = -1;
43 char *file = NULL;
44 int ret = -1;
45 char *pattern = NULL;
46 char *buf = NULL;
47 virStreamPtr st = NULL;
48 size_t i;
49 virConnectPtr conn = NULL;
50 int flags = 0;
52 if (!blocking)
53 flags |= VIR_STREAM_NONBLOCK;
55 if (!(conn = virConnectOpen("test:///default")))
56 goto cleanup;
58 if (VIR_ALLOC_N(pattern, PATTERN_LEN) < 0 ||
59 VIR_ALLOC_N(buf, PATTERN_LEN) < 0)
60 goto cleanup;
62 for (i = 0; i < PATTERN_LEN; i++)
63 pattern[i] = i;
65 if (virAsprintf(&file, "%s/input.data", scratchdir) < 0)
66 goto cleanup;
68 if ((fd = open(file, O_CREAT|O_WRONLY|O_EXCL, 0600)) < 0)
69 goto cleanup;
71 for (i = 0; i < 10; i++) {
72 if (safewrite(fd, pattern, PATTERN_LEN) != PATTERN_LEN)
73 goto cleanup;
76 if (VIR_CLOSE(fd) < 0)
77 goto cleanup;
79 if (!(st = virStreamNew(conn, flags)))
80 goto cleanup;
82 /* Start reading 1/2 way through first pattern
83 * and end 1/2 way through last pattern
85 if (virFDStreamOpenFile(st, file,
86 PATTERN_LEN / 2, PATTERN_LEN * 9,
87 O_RDONLY) < 0)
88 goto cleanup;
90 for (i = 0; i < 10; i++) {
91 size_t offset = 0;
92 size_t want;
93 if (i == 0)
94 want = PATTERN_LEN / 2;
95 else
96 want = PATTERN_LEN;
98 while (want > 0) {
99 int got;
100 reread:
101 got = st->driver->streamRecv(st, buf + offset, want);
102 if (got < 0) {
103 if (got == -2 && !blocking) {
104 usleep(20 * 1000);
105 goto reread;
107 virFilePrintf(stderr, "Failed to read stream: %s\n",
108 virGetLastErrorMessage());
109 goto cleanup;
111 if (got == 0) {
112 /* Expect EOF 1/2 through last pattern */
113 if (i == 9 && want == (PATTERN_LEN / 2))
114 break;
115 virFilePrintf(stderr, "Unexpected EOF block %zu want %zu\n",
116 i, want);
117 goto cleanup;
119 offset += got;
120 want -= got;
122 if (i == 0) {
123 if (memcmp(buf, pattern + (PATTERN_LEN / 2), PATTERN_LEN / 2) != 0) {
124 virFilePrintf(stderr, "Mismatched pattern data iteration %zu\n", i);
125 goto cleanup;
127 } else if (i == 9) {
128 if (memcmp(buf, pattern, PATTERN_LEN / 2) != 0) {
129 virFilePrintf(stderr, "Mismatched pattern data iteration %zu\n", i);
130 goto cleanup;
132 } else {
133 if (memcmp(buf, pattern, PATTERN_LEN) != 0) {
134 virFilePrintf(stderr, "Mismatched pattern data iteration %zu\n", i);
135 goto cleanup;
140 if (st->driver->streamFinish(st) != 0) {
141 virFilePrintf(stderr, "Failed to finish stream: %s\n",
142 virGetLastErrorMessage());
143 goto cleanup;
146 ret = 0;
147 cleanup:
148 if (st)
149 virStreamFree(st);
150 VIR_FORCE_CLOSE(fd);
151 if (file != NULL)
152 unlink(file);
153 if (conn)
154 virConnectClose(conn);
155 VIR_FREE(file);
156 VIR_FREE(pattern);
157 VIR_FREE(buf);
158 return ret;
162 static int testFDStreamReadBlock(const void *data)
164 return testFDStreamReadCommon(data, true);
166 static int testFDStreamReadNonblock(const void *data)
168 return testFDStreamReadCommon(data, false);
172 static int testFDStreamWriteCommon(const char *scratchdir, bool blocking)
174 int fd = -1;
175 char *file = NULL;
176 int ret = -1;
177 char *pattern = NULL;
178 char *buf = NULL;
179 virStreamPtr st = NULL;
180 size_t i;
181 virConnectPtr conn = NULL;
182 int flags = 0;
184 if (!blocking)
185 flags |= VIR_STREAM_NONBLOCK;
187 if (!(conn = virConnectOpen("test:///default")))
188 goto cleanup;
190 if (VIR_ALLOC_N(pattern, PATTERN_LEN) < 0 ||
191 VIR_ALLOC_N(buf, PATTERN_LEN) < 0)
192 goto cleanup;
194 for (i = 0; i < PATTERN_LEN; i++)
195 pattern[i] = i;
197 if (virAsprintf(&file, "%s/input.data", scratchdir) < 0)
198 goto cleanup;
200 if (!(st = virStreamNew(conn, flags)))
201 goto cleanup;
203 /* Start writing 1/2 way through first pattern
204 * and end 1/2 way through last pattern
206 if (virFDStreamCreateFile(st, file,
207 PATTERN_LEN / 2, PATTERN_LEN * 9,
208 O_WRONLY, 0600) < 0)
209 goto cleanup;
211 for (i = 0; i < 10; i++) {
212 size_t offset = 0;
213 size_t want;
214 if (i == 0)
215 want = PATTERN_LEN / 2;
216 else
217 want = PATTERN_LEN;
219 while (want > 0) {
220 int got;
221 rewrite:
222 got = st->driver->streamSend(st, pattern + offset, want);
223 if (got < 0) {
224 if (got == -2 && !blocking) {
225 usleep(20 * 1000);
226 goto rewrite;
228 if (i == 9 &&
229 want == (PATTERN_LEN / 2))
230 break;
231 virFilePrintf(stderr, "Failed to write stream: %s\n",
232 virGetLastErrorMessage());
233 goto cleanup;
235 offset += got;
236 want -= got;
240 if (st->driver->streamFinish(st) != 0) {
241 virFilePrintf(stderr, "Failed to finish stream: %s\n",
242 virGetLastErrorMessage());
243 goto cleanup;
246 if ((fd = open(file, O_RDONLY)) < 0)
247 goto cleanup;
249 for (i = 0; i < 10; i++) {
250 size_t want, got;
251 if (i == 9)
252 want = PATTERN_LEN / 2;
253 else
254 want = PATTERN_LEN;
256 if ((got = saferead(fd, buf, want)) != want) {
257 virFilePrintf(stderr,
258 "Short read from data, i=%zu got=%zu want=%zu\n",
259 i, got, want);
260 goto cleanup;
263 if (i == 0) {
264 size_t j;
265 for (j = 0; j < (PATTERN_LEN / 2); j++) {
266 if (buf[j] != 0) {
267 virFilePrintf(stderr, "Mismatched pattern data iteration %zu\n", i);
268 goto cleanup;
271 if (memcmp(buf + (PATTERN_LEN / 2), pattern, PATTERN_LEN / 2) != 0) {
272 virFilePrintf(stderr, "Mismatched pattern data iteration %zu\n", i);
273 goto cleanup;
275 } else if (i == 9) {
276 if (memcmp(buf, pattern, PATTERN_LEN / 2) != 0) {
277 virFilePrintf(stderr, "Mismatched pattern data iteration %zu\n", i);
278 goto cleanup;
280 } else {
281 if (memcmp(buf, pattern, PATTERN_LEN) != 0) {
282 virFilePrintf(stderr, "Mismatched pattern data iteration %zu\n", i);
283 goto cleanup;
288 if (VIR_CLOSE(fd) < 0)
289 goto cleanup;
291 ret = 0;
292 cleanup:
293 if (st)
294 virStreamFree(st);
295 VIR_FORCE_CLOSE(fd);
296 if (file != NULL)
297 unlink(file);
298 if (conn)
299 virConnectClose(conn);
300 VIR_FREE(file);
301 VIR_FREE(pattern);
302 VIR_FREE(buf);
303 return ret;
307 static int testFDStreamWriteBlock(const void *data)
309 return testFDStreamWriteCommon(data, true);
311 static int testFDStreamWriteNonblock(const void *data)
313 return testFDStreamWriteCommon(data, false);
316 #define SCRATCHDIRTEMPLATE abs_builddir "/fdstreamdir-XXXXXX"
318 static int
319 mymain(void)
321 char scratchdir[] = SCRATCHDIRTEMPLATE;
322 int ret = 0;
324 if (!mkdtemp(scratchdir)) {
325 virFilePrintf(stderr, "Cannot create fdstreamdir");
326 abort();
329 if (virTestRun("Stream read blocking ", testFDStreamReadBlock, scratchdir) < 0)
330 ret = -1;
331 if (virTestRun("Stream read non-blocking ", testFDStreamReadNonblock, scratchdir) < 0)
332 ret = -1;
333 if (virTestRun("Stream write blocking ", testFDStreamWriteBlock, scratchdir) < 0)
334 ret = -1;
335 if (virTestRun("Stream write non-blocking ", testFDStreamWriteNonblock, scratchdir) < 0)
336 ret = -1;
338 if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
339 virFileDeleteTree(scratchdir);
341 return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
344 VIR_TEST_MAIN(mymain)