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/>.
23 #include "testutils.h"
25 #include "virfdstream.h"
26 #include "datatypes.h"
30 #include "virstring.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
)
47 virStreamPtr st
= NULL
;
49 virConnectPtr conn
= NULL
;
53 flags
|= VIR_STREAM_NONBLOCK
;
55 if (!(conn
= virConnectOpen("test:///default")))
58 if (VIR_ALLOC_N(pattern
, PATTERN_LEN
) < 0 ||
59 VIR_ALLOC_N(buf
, PATTERN_LEN
) < 0)
62 for (i
= 0; i
< PATTERN_LEN
; i
++)
65 if (virAsprintf(&file
, "%s/input.data", scratchdir
) < 0)
68 if ((fd
= open(file
, O_CREAT
|O_WRONLY
|O_EXCL
, 0600)) < 0)
71 for (i
= 0; i
< 10; i
++) {
72 if (safewrite(fd
, pattern
, PATTERN_LEN
) != PATTERN_LEN
)
76 if (VIR_CLOSE(fd
) < 0)
79 if (!(st
= virStreamNew(conn
, flags
)))
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,
90 for (i
= 0; i
< 10; i
++) {
94 want
= PATTERN_LEN
/ 2;
101 got
= st
->driver
->streamRecv(st
, buf
+ offset
, want
);
103 if (got
== -2 && !blocking
) {
107 virFilePrintf(stderr
, "Failed to read stream: %s\n",
108 virGetLastErrorMessage());
112 /* Expect EOF 1/2 through last pattern */
113 if (i
== 9 && want
== (PATTERN_LEN
/ 2))
115 virFilePrintf(stderr
, "Unexpected EOF block %zu want %zu\n",
123 if (memcmp(buf
, pattern
+ (PATTERN_LEN
/ 2), PATTERN_LEN
/ 2) != 0) {
124 virFilePrintf(stderr
, "Mismatched pattern data iteration %zu\n", i
);
128 if (memcmp(buf
, pattern
, PATTERN_LEN
/ 2) != 0) {
129 virFilePrintf(stderr
, "Mismatched pattern data iteration %zu\n", i
);
133 if (memcmp(buf
, pattern
, PATTERN_LEN
) != 0) {
134 virFilePrintf(stderr
, "Mismatched pattern data iteration %zu\n", i
);
140 if (st
->driver
->streamFinish(st
) != 0) {
141 virFilePrintf(stderr
, "Failed to finish stream: %s\n",
142 virGetLastErrorMessage());
154 virConnectClose(conn
);
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
)
177 char *pattern
= NULL
;
179 virStreamPtr st
= NULL
;
181 virConnectPtr conn
= NULL
;
185 flags
|= VIR_STREAM_NONBLOCK
;
187 if (!(conn
= virConnectOpen("test:///default")))
190 if (VIR_ALLOC_N(pattern
, PATTERN_LEN
) < 0 ||
191 VIR_ALLOC_N(buf
, PATTERN_LEN
) < 0)
194 for (i
= 0; i
< PATTERN_LEN
; i
++)
197 if (virAsprintf(&file
, "%s/input.data", scratchdir
) < 0)
200 if (!(st
= virStreamNew(conn
, flags
)))
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,
211 for (i
= 0; i
< 10; i
++) {
215 want
= PATTERN_LEN
/ 2;
222 got
= st
->driver
->streamSend(st
, pattern
+ offset
, want
);
224 if (got
== -2 && !blocking
) {
229 want
== (PATTERN_LEN
/ 2))
231 virFilePrintf(stderr
, "Failed to write stream: %s\n",
232 virGetLastErrorMessage());
240 if (st
->driver
->streamFinish(st
) != 0) {
241 virFilePrintf(stderr
, "Failed to finish stream: %s\n",
242 virGetLastErrorMessage());
246 if ((fd
= open(file
, O_RDONLY
)) < 0)
249 for (i
= 0; i
< 10; i
++) {
252 want
= PATTERN_LEN
/ 2;
256 if ((got
= saferead(fd
, buf
, want
)) != want
) {
257 virFilePrintf(stderr
,
258 "Short read from data, i=%zu got=%zu want=%zu\n",
265 for (j
= 0; j
< (PATTERN_LEN
/ 2); j
++) {
267 virFilePrintf(stderr
, "Mismatched pattern data iteration %zu\n", i
);
271 if (memcmp(buf
+ (PATTERN_LEN
/ 2), pattern
, PATTERN_LEN
/ 2) != 0) {
272 virFilePrintf(stderr
, "Mismatched pattern data iteration %zu\n", i
);
276 if (memcmp(buf
, pattern
, PATTERN_LEN
/ 2) != 0) {
277 virFilePrintf(stderr
, "Mismatched pattern data iteration %zu\n", i
);
281 if (memcmp(buf
, pattern
, PATTERN_LEN
) != 0) {
282 virFilePrintf(stderr
, "Mismatched pattern data iteration %zu\n", i
);
288 if (VIR_CLOSE(fd
) < 0)
299 virConnectClose(conn
);
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"
321 char scratchdir
[] = SCRATCHDIRTEMPLATE
;
324 if (!mkdtemp(scratchdir
)) {
325 virFilePrintf(stderr
, "Cannot create fdstreamdir");
329 if (virTestRun("Stream read blocking ", testFDStreamReadBlock
, scratchdir
) < 0)
331 if (virTestRun("Stream read non-blocking ", testFDStreamReadNonblock
, scratchdir
) < 0)
333 if (virTestRun("Stream write blocking ", testFDStreamWriteBlock
, scratchdir
) < 0)
335 if (virTestRun("Stream write non-blocking ", testFDStreamWriteNonblock
, scratchdir
) < 0)
338 if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL
)
339 virFileDeleteTree(scratchdir
);
341 return ret
== 0 ? EXIT_SUCCESS
: EXIT_FAILURE
;
344 VIR_TEST_MAIN(mymain
)