2 * testutils.c: basic test utils
4 * Copyright (C) 2005-2015 Red Hat, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see
18 * <http://www.gnu.org/licenses/>.
25 #include <sys/types.h>
31 #include "testutils.h"
35 #include "virthread.h"
37 #include "virbuffer.h"
39 #include "vircommand.h"
40 #include "virrandom.h"
42 #include "virprocess.h"
43 #include "virstring.h"
46 # ifdef TEST_OOM_TRACE
48 # include <execinfo.h>
52 #define VIR_FROM_THIS VIR_FROM_NONE
54 VIR_LOG_INIT("tests.testutils");
56 #include "virbitmap.h"
59 static unsigned int testDebug
= -1;
60 static unsigned int testVerbose
= -1;
61 static unsigned int testExpensive
= -1;
62 static unsigned int testRegenerate
= -1;
65 static unsigned int testOOM
;
66 static unsigned int testOOMStart
= -1;
67 static unsigned int testOOMEnd
= -1;
68 static unsigned int testOOMTrace
;
69 # ifdef TEST_OOM_TRACE
70 void *testAllocStack
[30];
74 static bool testOOMActive
;
76 static size_t testCounter
;
77 static virBitmapPtr testBitmap
;
82 bool virTestOOMActive(void)
87 static int virTestUseTerminalColors(void)
89 return isatty(STDOUT_FILENO
);
93 virTestGetFlag(const char *name
)
98 if ((flagStr
= getenv(name
)) == NULL
)
101 if (virStrToLong_ui(flagStr
, NULL
, 10, &flag
) < 0)
107 #ifdef TEST_OOM_TRACE
108 static void virTestAllocHook(int nalloc ATTRIBUTE_UNUSED
,
109 void *opaque ATTRIBUTE_UNUSED
)
111 ntestAllocStack
= backtrace(testAllocStack
, ARRAY_CARDINALITY(testAllocStack
));
115 #ifdef TEST_OOM_TRACE
117 virTestShowTrace(void)
120 for (j
= 2; j
< ntestAllocStack
; j
++) {
124 dladdr(testAllocStack
[j
], &info
);
125 if (info
.dli_fname
&&
126 strstr(info
.dli_fname
, ".so")) {
127 if (virAsprintf(&cmd
, ADDR2LINE
" -f -e %s %p",
129 ((void*)((unsigned long long)testAllocStack
[j
]
130 - (unsigned long long)info
.dli_fbase
))) < 0)
133 if (virAsprintf(&cmd
, ADDR2LINE
" -f -e %s %p",
134 (char*)(info
.dli_fname
? info
.dli_fname
: "<unknown>"),
135 testAllocStack
[j
]) < 0)
138 ignore_value(system(cmd
));
147 * returns: -1 = error, 0 = success
150 virTestRun(const char *title
,
151 int (*body
)(const void *data
), const void *data
)
155 /* Some test are fragile about environ settings. If that's
156 * the case, don't poison it. */
157 if (getenv("VIR_TEST_MOCK_PROGNAME"))
158 setenv("VIR_TEST_MOCK_TESTNAME", title
, 1);
160 if (testCounter
== 0 && !virTestGetVerbose())
161 fprintf(stderr
, " ");
166 /* Skip tests if out of range */
167 if (testBitmap
&& !virBitmapIsBitSet(testBitmap
, testCounter
))
170 if (virTestGetVerbose())
171 fprintf(stderr
, "%2zu) %-65s ... ", testCounter
, title
);
175 if (virGetLastErrorCode()) {
176 if (virTestGetVerbose() || virTestGetDebug())
177 virDispatchError(NULL
);
180 if (virTestGetVerbose()) {
182 if (virTestUseTerminalColors())
183 fprintf(stderr
, "\e[32mOK\e[0m\n"); /* green */
185 fprintf(stderr
, "OK\n");
186 else if (ret
== EXIT_AM_SKIP
)
187 if (virTestUseTerminalColors())
188 fprintf(stderr
, "\e[34m\e[1mSKIP\e[0m\n"); /* bold blue */
190 fprintf(stderr
, "SKIP\n");
192 if (virTestUseTerminalColors())
193 fprintf(stderr
, "\e[31m\e[1mFAILED\e[0m\n"); /* bold red */
195 fprintf(stderr
, "FAILED\n");
197 if (testCounter
!= 1 &&
198 !((testCounter
-1) % 40)) {
199 fprintf(stderr
, " %-3zu\n", (testCounter
-1));
200 fprintf(stderr
, " ");
203 fprintf(stderr
, ".");
204 else if (ret
== EXIT_AM_SKIP
)
205 fprintf(stderr
, "_");
207 fprintf(stderr
, "!");
211 if (testOOM
&& ret
!= EXIT_AM_SKIP
) {
218 # ifdef TEST_OOM_TRACE
219 virAllocTestHook(virTestAllocHook
, NULL
);
222 nalloc
= virAllocTestCount();
223 fprintf(stderr
, " Test OOM for nalloc=%d ", nalloc
);
224 if (testOOMStart
== -1 ||
229 start
= testOOMStart
;
230 end
= testOOMEnd
+ 1;
232 testOOMActive
= true;
233 for (i
= start
; i
< end
; i
++) {
234 bool missingFail
= false;
235 # ifdef TEST_OOM_TRACE
236 memset(testAllocStack
, 0, sizeof(testAllocStack
));
239 virAllocTestOOM(i
+ 1, 1);
242 /* fprintf() disabled because XML parsing APIs don't allow
243 * distinguish between element / attribute not present
244 * in the XML (which is non-fatal), vs OOM / malformed
245 * which should be fatal. Thus error reporting for
246 * optionally present XML is mostly broken.
251 fprintf(stderr
, " alloc %zu failed but no err status\n", i
+ 1);
254 if (virGetLastErrorCode() == VIR_ERR_OK
) {
256 fprintf(stderr
, " alloc %zu failed but no error report\n", i
+ 1);
261 if ((missingFail
&& testOOMTrace
) || (testOOMTrace
> 1)) {
262 fprintf(stderr
, "%s", "!");
263 # ifdef TEST_OOM_TRACE
268 fprintf(stderr
, "%s", ".");
271 testOOMActive
= false;
273 fprintf(stderr
, " OK\n");
275 fprintf(stderr
, " FAILED\n");
278 #endif /* TEST_OOM */
280 unsetenv("VIR_TEST_MOCK_TESTNAME");
287 * @file: name of the file to load
288 * @buf: buffer to load the file into
290 * Allocates @buf to the size of FILE. Reads FILE into buffer BUF.
291 * Upon any failure, error is printed to stderr and -1 is returned. 'errno' is
292 * not preserved. On success 0 is returned. Caller is responsible for freeing
296 virTestLoadFile(const char *file
, char **buf
)
298 FILE *fp
= fopen(file
, "r");
301 int len
, tmplen
, buflen
;
304 fprintf(stderr
, "%s: failed to open: %s\n", file
, strerror(errno
));
308 if (fstat(fileno(fp
), &st
) < 0) {
309 fprintf(stderr
, "%s: failed to fstat: %s\n", file
, strerror(errno
));
310 VIR_FORCE_FCLOSE(fp
);
314 tmplen
= buflen
= st
.st_size
+ 1;
316 if (VIR_ALLOC_N(*buf
, buflen
) < 0) {
317 VIR_FORCE_FCLOSE(fp
);
324 /* read the file line by line */
325 while (fgets(tmp
, tmplen
, fp
) != NULL
) {
327 /* stop on an empty line */
330 /* remove trailing backslash-newline pair */
331 if (len
>= 2 && tmp
[len
-2] == '\\' && tmp
[len
-1] == '\n') {
335 /* advance the temporary buffer pointer */
340 fprintf(stderr
, "%s: read failed: %s\n", file
, strerror(errno
));
341 VIR_FORCE_FCLOSE(fp
);
347 VIR_FORCE_FCLOSE(fp
);
353 virTestLoadFileGetPath(const char *p
,
356 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
359 virBufferAddLit(&buf
, abs_srcdir
"/");
362 virBufferAdd(&buf
, p
, -1);
363 virBufferStrcatVArgs(&buf
, ap
);
366 if (!(path
= virBufferContentAndReset(&buf
)))
367 VIR_TEST_VERBOSE("failed to format file path");
374 * virTestLoadFilePath:
375 * @...: file name components terminated with a NULL
377 * Constructs the test file path from variable arguments and loads the file.
378 * 'abs_srcdir' is automatically prepended.
381 virTestLoadFilePath(const char *p
, ...)
389 if (!(path
= virTestLoadFileGetPath(p
, ap
)))
392 ignore_value(virTestLoadFile(path
, &ret
));
403 * virTestLoadFileJSON:
404 * @...: name components terminated with a NULL
406 * Constructs the test file path from variable arguments and loads and parses
407 * the JSON file. 'abs_srcdir' is automatically prepended to the path.
410 virTestLoadFileJSON(const char *p
, ...)
412 virJSONValuePtr ret
= NULL
;
413 char *jsonstr
= NULL
;
419 if (!(path
= virTestLoadFileGetPath(p
, ap
)))
422 if (virTestLoadFile(path
, &jsonstr
) < 0)
425 if (!(ret
= virJSONValueFromString(jsonstr
)))
426 VIR_TEST_VERBOSE("failed to parse json from file '%s'", path
);
438 void virTestCaptureProgramExecChild(const char *const argv
[],
444 const char *const env
[] = {
449 if ((stdinfd
= open("/dev/null", O_RDONLY
)) < 0)
452 open_max
= sysconf(_SC_OPEN_MAX
);
456 for (i
= 0; i
< open_max
; i
++) {
461 VIR_FORCE_CLOSE(tmpfd
);
465 if (dup2(stdinfd
, STDIN_FILENO
) != STDIN_FILENO
)
467 if (dup2(pipefd
, STDOUT_FILENO
) != STDOUT_FILENO
)
469 if (dup2(pipefd
, STDERR_FILENO
) != STDERR_FILENO
)
472 /* SUS is crazy here, hence the cast */
473 execve(argv
[0], (char *const*)argv
, (char *const*)env
);
476 VIR_FORCE_CLOSE(stdinfd
);
480 virTestCaptureProgramOutput(const char *const argv
[], char **buf
, int maxlen
)
485 if (pipe(pipefd
) < 0)
491 VIR_FORCE_CLOSE(pipefd
[0]);
492 virTestCaptureProgramExecChild(argv
, pipefd
[1]);
494 VIR_FORCE_CLOSE(pipefd
[1]);
501 VIR_FORCE_CLOSE(pipefd
[1]);
502 len
= virFileReadLimFD(pipefd
[0], maxlen
, buf
);
503 VIR_FORCE_CLOSE(pipefd
[0]);
504 if (virProcessWait(pid
, NULL
, false) < 0)
512 virTestCaptureProgramOutput(const char *const argv
[] ATTRIBUTE_UNUSED
,
513 char **buf ATTRIBUTE_UNUSED
,
514 int maxlen ATTRIBUTE_UNUSED
)
521 virTestRewrapFile(const char *filename
)
525 virCommandPtr cmd
= NULL
;
527 if (!(virStringHasSuffix(filename
, ".args") ||
528 virStringHasSuffix(filename
, ".ldargs")))
532 fprintf(stderr
, "cannot rewrap %s: unable to find perl in path", filename
);
536 if (virAsprintf(&script
, "%s/test-wrap-argv.pl", abs_srcdir
) < 0)
539 cmd
= virCommandNewArgList(perl
, script
, "--in-place", filename
, NULL
);
540 if (virCommandRun(cmd
, NULL
) < 0)
551 * @param stream: output stream to write differences to
552 * @param expect: expected output text
553 * @param expectName: name designator of the expected text
554 * @param actual: actual output text
555 * @param actualName: name designator of the actual text
556 * @param regenerate: enable or disable regenerate functionality
558 * Display expected and actual output text, trimmed to first and last
559 * characters at which differences occur. Displays names of the text strings if
563 virTestDifferenceFullInternal(FILE *stream
,
565 const char *expectName
,
567 const char *actualName
,
570 const char *expectStart
;
571 const char *expectEnd
;
572 const char *actualStart
;
573 const char *actualEnd
;
580 expectStart
= expect
;
581 expectEnd
= expect
+ (strlen(expect
)-1);
582 actualStart
= actual
;
583 actualEnd
= actual
+ (strlen(actual
)-1);
585 if (expectName
&& regenerate
&& (virTestGetRegenerate() > 0)) {
586 if (virFileWriteStr(expectName
, actual
, 0666) < 0) {
587 virDispatchError(NULL
);
591 if (virTestRewrapFile(expectName
) < 0) {
592 virDispatchError(NULL
);
597 if (!virTestGetDebug())
600 if (virTestGetDebug() < 2) {
601 /* Skip to first character where they differ */
602 while (*expectStart
&& *actualStart
&&
603 *actualStart
== *expectStart
) {
608 /* Work backwards to last character where they differ */
609 while (actualEnd
> actualStart
&&
610 expectEnd
> expectStart
&&
611 *actualEnd
== *expectEnd
) {
617 /* Show the trimmed differences */
619 fprintf(stream
, "\nIn '%s':", expectName
);
620 fprintf(stream
, "\nOffset %d\nExpect [", (int) (expectStart
- expect
));
621 if ((expectEnd
- expectStart
+ 1) &&
622 fwrite(expectStart
, (expectEnd
-expectStart
+1), 1, stream
) != 1)
624 fprintf(stream
, "]\n");
626 fprintf(stream
, "In '%s':\n", actualName
);
627 fprintf(stream
, "Actual [");
628 if ((actualEnd
- actualStart
+ 1) &&
629 fwrite(actualStart
, (actualEnd
-actualStart
+1), 1, stream
) != 1)
631 fprintf(stream
, "]\n");
633 /* Pad to line up with test name ... in virTestRun */
634 fprintf(stream
, " ... ");
640 * @param stream: output stream to write differences to
641 * @param expect: expected output text
642 * @param expectName: name designator of the expected text
643 * @param actual: actual output text
644 * @param actualName: name designator of the actual text
646 * Display expected and actual output text, trimmed to first and last
647 * characters at which differences occur. Displays names of the text strings if
648 * non-NULL. If VIR_TEST_REGENERATE_OUTPUT is used, this function will
649 * regenerate the expected file.
652 virTestDifferenceFull(FILE *stream
,
654 const char *expectName
,
656 const char *actualName
)
658 return virTestDifferenceFullInternal(stream
, expect
, expectName
,
659 actual
, actualName
, true);
663 * @param stream: output stream to write differences to
664 * @param expect: expected output text
665 * @param expectName: name designator of the expected text
666 * @param actual: actual output text
667 * @param actualName: name designator of the actual text
669 * Display expected and actual output text, trimmed to first and last
670 * characters at which differences occur. Displays names of the text strings if
671 * non-NULL. If VIR_TEST_REGENERATE_OUTPUT is used, this function will not
672 * regenerate the expected file.
675 virTestDifferenceFullNoRegenerate(FILE *stream
,
677 const char *expectName
,
679 const char *actualName
)
681 return virTestDifferenceFullInternal(stream
, expect
, expectName
,
682 actual
, actualName
, false);
686 * @param stream: output stream to write differences to
687 * @param expect: expected output text
688 * @param actual: actual output text
690 * Display expected and actual output text, trimmed to
691 * first and last characters at which differences occur
694 virTestDifference(FILE *stream
,
698 return virTestDifferenceFullNoRegenerate(stream
,
705 * @param stream: output stream to write differences to
706 * @param expect: expected output text
707 * @param actual: actual output text
709 * Display expected and actual output text, trimmed to
710 * first and last characters at which differences occur
712 int virTestDifferenceBin(FILE *stream
,
717 size_t start
= 0, end
= length
;
720 if (!virTestGetDebug())
723 if (virTestGetDebug() < 2) {
724 /* Skip to first character where they differ */
725 for (i
= 0; i
< length
; i
++) {
726 if (expect
[i
] != actual
[i
]) {
732 /* Work backwards to last character where they differ */
733 for (i
= (length
-1); i
>= 0; i
--) {
734 if (expect
[i
] != actual
[i
]) {
740 /* Round to nearest boundary of 4, except that last word can be short */
741 start
-= (start
% 4);
742 end
+= 4 - (end
% 4);
746 /* Show the trimmed differences */
747 fprintf(stream
, "\nExpect [ Region %d-%d", (int)start
, (int)end
);
748 for (i
= start
; i
< end
; i
++) {
750 fprintf(stream
, "\n ");
751 fprintf(stream
, "0x%02x, ", ((int)expect
[i
])&0xff);
753 fprintf(stream
, "]\n");
754 fprintf(stream
, "Actual [ Region %d-%d", (int)start
, (int)end
);
755 for (i
= start
; i
< end
; i
++) {
757 fprintf(stream
, "\n ");
758 fprintf(stream
, "0x%02x, ", ((int)actual
[i
])&0xff);
760 fprintf(stream
, "]\n");
762 /* Pad to line up with test name ... in virTestRun */
763 fprintf(stream
, " ... ");
769 * @param actual: String input content
770 * @param filename: File to compare @actual against
772 * If @actual is NULL, it's treated as an empty string.
775 virTestCompareToFile(const char *actual
,
776 const char *filename
)
779 char *filecontent
= NULL
;
780 char *fixedcontent
= NULL
;
781 const char *cmpcontent
= actual
;
786 if (virTestLoadFile(filename
, &filecontent
) < 0 && !virTestGetRegenerate())
790 size_t filecontentLen
= strlen(filecontent
);
791 size_t cmpcontentLen
= strlen(cmpcontent
);
793 if (filecontentLen
> 0 &&
794 filecontent
[filecontentLen
- 1] == '\n' &&
795 (cmpcontentLen
== 0 || cmpcontent
[cmpcontentLen
- 1] != '\n')) {
796 if (virAsprintf(&fixedcontent
, "%s\n", cmpcontent
) < 0)
798 cmpcontent
= fixedcontent
;
802 if (STRNEQ_NULLABLE(cmpcontent
, filecontent
)) {
803 virTestDifferenceFull(stderr
,
804 filecontent
, filename
,
811 VIR_FREE(fixedcontent
);
812 VIR_FREE(filecontent
);
817 virTestCompareToULL(unsigned long long expect
,
818 unsigned long long actual
)
820 VIR_AUTOFREE(char *) expectStr
= NULL
;
821 VIR_AUTOFREE(char *) actualStr
= NULL
;
823 if (virAsprintf(&expectStr
, "%llu", expect
) < 0)
826 if (virAsprintf(&actualStr
, "%llu", actual
) < 0)
829 return virTestCompareToString(expectStr
, actualStr
);
833 virTestCompareToString(const char *expect
,
836 if (STRNEQ_NULLABLE(expect
, actual
)) {
837 virTestDifference(stderr
, expect
, actual
);
845 virTestErrorFuncQuiet(void *data ATTRIBUTE_UNUSED
,
846 virErrorPtr err ATTRIBUTE_UNUSED
)
850 /* register an error handler in tests when using connections */
852 virTestQuiesceLibvirtErrors(bool always
)
854 if (always
|| !virTestGetVerbose())
855 virSetErrorFunc(NULL
, virTestErrorFuncQuiet
);
858 struct virtTestLogData
{
862 static struct virtTestLogData testLog
= { VIR_BUFFER_INITIALIZER
};
865 virtTestLogOutput(virLogSourcePtr source ATTRIBUTE_UNUSED
,
866 virLogPriority priority ATTRIBUTE_UNUSED
,
867 const char *filename ATTRIBUTE_UNUSED
,
868 int lineno ATTRIBUTE_UNUSED
,
869 const char *funcname ATTRIBUTE_UNUSED
,
870 const char *timestamp
,
871 virLogMetadataPtr metadata ATTRIBUTE_UNUSED
,
873 const char *rawstr ATTRIBUTE_UNUSED
,
877 struct virtTestLogData
*log
= data
;
878 virCheckFlags(VIR_LOG_STACK_TRACE
,);
880 virBufferAsprintf(&log
->buf
, "%s: %s", timestamp
, str
);
884 virtTestLogClose(void *data
)
886 struct virtTestLogData
*log
= data
;
888 virBufferFreeAndReset(&log
->buf
);
891 /* Return a malloc'd string (possibly with strlen of 0) of all data
892 * logged since the last call to this function, or NULL on failure. */
894 virTestLogContentAndReset(void)
898 if (virBufferError(&testLog
.buf
))
900 ret
= virBufferContentAndReset(&testLog
.buf
);
902 ignore_value(VIR_STRDUP(ret
, ""));
908 virTestGetDebug(void)
911 testDebug
= virTestGetFlag("VIR_TEST_DEBUG");
916 virTestGetVerbose(void)
918 if (testVerbose
== -1)
919 testVerbose
= virTestGetFlag("VIR_TEST_VERBOSE");
920 return testVerbose
|| virTestGetDebug();
924 virTestGetExpensive(void)
926 if (testExpensive
== -1)
927 testExpensive
= virTestGetFlag("VIR_TEST_EXPENSIVE");
928 return testExpensive
;
932 virTestGetRegenerate(void)
934 if (testRegenerate
== -1)
935 testRegenerate
= virTestGetFlag("VIR_TEST_REGENERATE_OUTPUT");
936 return testRegenerate
;
940 virTestSetEnvPath(void)
943 const char *path
= getenv("PATH");
944 char *new_path
= NULL
;
947 if (strstr(path
, abs_builddir
) != path
&&
948 virAsprintf(&new_path
, "%s:%s", abs_builddir
, path
) < 0)
951 if (VIR_STRDUP(new_path
, abs_builddir
) < 0)
956 setenv("PATH", new_path
, 1) < 0)
965 #define TEST_MOCK (abs_builddir "/.libs/virtestmock.so")
967 int virTestMain(int argc
,
975 char *testRange
= NULL
;
980 virLogOutputPtr output
= NULL
;
981 virLogOutputPtr
*outputs
= NULL
;
983 if (getenv("VIR_TEST_FILE_ACCESS"))
984 VIR_TEST_PRELOAD(TEST_MOCK
);
987 while ((lib
= va_arg(ap
, const char *)))
988 VIR_TEST_PRELOAD(lib
);
991 progname
= last_component(argv
[0]);
992 if (STRPREFIX(progname
, "lt-"))
995 setenv("VIR_TEST_MOCK_PROGNAME", progname
, 1);
997 virFileActivateDirOverride(argv
[0]);
999 if (virTestSetEnvPath() < 0)
1000 return EXIT_AM_HARDFAIL
;
1002 if (!virFileExists(abs_srcdir
))
1003 return EXIT_AM_HARDFAIL
;
1006 fprintf(stderr
, "Usage: %s\n", argv
[0]);
1007 fputs("effective environment variables:\n"
1008 "VIR_TEST_VERBOSE set to show names of individual tests\n"
1009 "VIR_TEST_DEBUG set to show information for debugging failures\n",
1011 return EXIT_FAILURE
;
1013 fprintf(stderr
, "TEST: %s\n", progname
);
1015 if (virThreadInitialize() < 0 ||
1016 virErrorInitialize() < 0)
1017 return EXIT_FAILURE
;
1020 if (!getenv("LIBVIRT_DEBUG") && !virLogGetNbOutputs()) {
1021 if (!(output
= virLogOutputNew(virtTestLogOutput
, virtTestLogClose
,
1022 &testLog
, VIR_LOG_DEBUG
,
1023 VIR_LOG_TO_STDERR
, NULL
)) ||
1024 VIR_APPEND_ELEMENT(outputs
, noutputs
, output
) < 0 ||
1025 virLogDefineOutputs(outputs
, noutputs
) < 0) {
1026 virLogOutputFree(output
);
1027 virLogOutputListFree(outputs
, noutputs
);
1028 return EXIT_FAILURE
;
1032 if ((testRange
= getenv("VIR_TEST_RANGE")) != NULL
) {
1033 if (!(testBitmap
= virBitmapParseUnlimited(testRange
))) {
1034 fprintf(stderr
, "Cannot parse range %s\n", testRange
);
1035 return EXIT_FAILURE
;
1040 if ((oomstr
= getenv("VIR_TEST_OOM")) != NULL
) {
1042 if (testDebug
== -1)
1045 if (oomstr
[0] != '\0' &&
1047 if (virStrToLong_ui(oomstr
+ 2, &next
, 10, &testOOMStart
) < 0) {
1048 fprintf(stderr
, "Cannot parse range %s\n", oomstr
);
1049 return EXIT_FAILURE
;
1051 if (*next
== '\0') {
1052 testOOMEnd
= testOOMStart
;
1055 fprintf(stderr
, "Cannot parse range %s\n", oomstr
);
1056 return EXIT_FAILURE
;
1058 if (virStrToLong_ui(next
+1, NULL
, 10, &testOOMEnd
) < 0) {
1059 fprintf(stderr
, "Cannot parse range %s\n", oomstr
);
1060 return EXIT_FAILURE
;
1069 # ifdef TEST_OOM_TRACE
1070 if ((oomstr
= getenv("VIR_TEST_OOM_TRACE")) != NULL
) {
1071 if (virStrToLong_ui(oomstr
, NULL
, 10, &testOOMTrace
) < 0) {
1072 fprintf(stderr
, "Cannot parse oom trace %s\n", oomstr
);
1073 return EXIT_FAILURE
;
1077 if (getenv("VIR_TEST_OOM_TRACE")) {
1078 fprintf(stderr
, "%s", "OOM test tracing not enabled in this build\n");
1079 return EXIT_FAILURE
;
1082 #else /* TEST_OOM */
1083 if (getenv("VIR_TEST_OOM")) {
1084 fprintf(stderr
, "%s", "OOM testing not enabled in this build\n");
1085 return EXIT_FAILURE
;
1087 if (getenv("VIR_TEST_OOM_TRACE")) {
1088 fprintf(stderr
, "%s", "OOM test tracing not enabled in this build\n");
1089 return EXIT_FAILURE
;
1091 #endif /* TEST_OOM */
1093 /* Find perl early because some tests override PATH */
1094 perl
= virFindFileInPath("perl");
1098 virResetLastError();
1099 if (!virTestGetVerbose() && ret
!= EXIT_AM_SKIP
) {
1100 if (testCounter
== 0 || testCounter
% 40)
1101 fprintf(stderr
, "%*s", 40 - (int)(testCounter
% 40), "");
1102 fprintf(stderr
, " %-3zu %s\n", testCounter
, ret
== 0 ? "OK" : "FAIL");
1111 * @cmdset contains a list of command line args, eg
1113 * "/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp --destination-port 53 --jump ACCEPT
1114 * /usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp --destination-port 53 --jump ACCEPT
1115 * /usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 --jump REJECT
1116 * /usr/sbin/iptables --table filter --insert FORWARD --out-interface virbr0 --jump REJECT
1117 * /usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 --out-interface virbr0 --jump ACCEPT"
1119 * And we're munging it in-place to strip the path component
1120 * of the command line, to produce
1122 * "iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp --destination-port 53 --jump ACCEPT
1123 * iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp --destination-port 53 --jump ACCEPT
1124 * iptables --table filter --insert FORWARD --in-interface virbr0 --jump REJECT
1125 * iptables --table filter --insert FORWARD --out-interface virbr0 --jump REJECT
1126 * iptables --table filter --insert FORWARD --in-interface virbr0 --out-interface virbr0 --jump ACCEPT"
1128 void virTestClearCommandPath(char *cmdset
)
1131 char *lineStart
= cmdset
;
1132 char *lineEnd
= strchr(lineStart
, '\n');
1138 dirsep
= strchr(lineStart
, ' ');
1140 while (dirsep
> lineStart
&& *dirsep
!= '/')
1146 movestart
= lineStart
;
1148 movelen
= lineEnd
? lineEnd
- movestart
: strlen(movestart
);
1151 memmove(cmdset
+ offset
, movestart
, movelen
+ 1);
1152 offset
+= movelen
+ 1;
1154 lineStart
= lineEnd
? lineEnd
+ 1 : NULL
;
1155 lineEnd
= lineStart
? strchr(lineStart
, '\n') : NULL
;
1157 cmdset
[offset
] = '\0';
1161 virCapsPtr
virTestGenericCapsInit(void)
1164 virCapsGuestPtr guest
;
1166 if ((caps
= virCapabilitiesNew(VIR_ARCH_X86_64
,
1167 false, false)) == NULL
)
1170 if ((guest
= virCapabilitiesAddGuest(caps
, VIR_DOMAIN_OSTYPE_HVM
, VIR_ARCH_I686
,
1171 "/usr/bin/acme-virt", NULL
,
1175 if (!virCapabilitiesAddGuestDomain(guest
, VIR_DOMAIN_VIRT_TEST
, NULL
, NULL
, 0, NULL
))
1177 if (!virCapabilitiesAddGuestDomain(guest
, VIR_DOMAIN_VIRT_QEMU
,
1178 NULL
, NULL
, 0, NULL
))
1180 if (!virCapabilitiesAddGuestDomain(guest
, VIR_DOMAIN_VIRT_KVM
,
1181 NULL
, NULL
, 0, NULL
))
1184 if ((guest
= virCapabilitiesAddGuest(caps
, VIR_DOMAIN_OSTYPE_HVM
, VIR_ARCH_X86_64
,
1185 "/usr/bin/acme-virt", NULL
,
1189 if (!virCapabilitiesAddGuestDomain(guest
, VIR_DOMAIN_VIRT_TEST
, NULL
, NULL
, 0, NULL
))
1191 if (!virCapabilitiesAddGuestDomain(guest
, VIR_DOMAIN_VIRT_QEMU
,
1192 NULL
, NULL
, 0, NULL
))
1194 if (!virCapabilitiesAddGuestDomain(guest
, VIR_DOMAIN_VIRT_KVM
,
1195 NULL
, NULL
, 0, NULL
))
1199 if (virTestGetDebug() > 1) {
1202 caps_str
= virCapabilitiesFormatXML(caps
);
1206 VIR_TEST_DEBUG("Generic driver capabilities:\n%s", caps_str
);
1214 virObjectUnref(caps
);
1220 #define MAX_CPUS_IN_CELL 2
1221 #define MAX_MEM_IN_CELL 2097152
1224 * Build NUMA topology with cell id starting from (0 + seq)
1228 virTestCapsBuildNUMATopology(virCapsPtr caps
,
1231 virCapsHostNUMACellCPUPtr cell_cpus
= NULL
;
1232 int core_id
, cell_id
;
1236 for (cell_id
= 0; cell_id
< MAX_CELLS
; cell_id
++) {
1237 if (VIR_ALLOC_N(cell_cpus
, MAX_CPUS_IN_CELL
) < 0)
1240 for (core_id
= 0; core_id
< MAX_CPUS_IN_CELL
; core_id
++) {
1241 cell_cpus
[core_id
].id
= id
+ core_id
;
1242 cell_cpus
[core_id
].socket_id
= cell_id
+ seq
;
1243 cell_cpus
[core_id
].core_id
= id
+ core_id
;
1244 if (!(cell_cpus
[core_id
].siblings
=
1245 virBitmapNew(MAX_CPUS_IN_CELL
)))
1247 ignore_value(virBitmapSetBit(cell_cpus
[core_id
].siblings
, id
));
1251 if (virCapabilitiesAddHostNUMACell(caps
, cell_id
+ seq
,
1253 MAX_CPUS_IN_CELL
, cell_cpus
,
1254 VIR_ARCH_NONE
, NULL
,
1255 VIR_ARCH_NONE
, NULL
) < 0)
1264 virCapabilitiesClearHostNUMACellCPUTopology(cell_cpus
, MAX_CPUS_IN_CELL
);
1265 VIR_FREE(cell_cpus
);
1269 static virDomainDefParserConfig virTestGenericDomainDefParserConfig
= {
1270 .features
= VIR_DOMAIN_DEF_FEATURE_INDIVIDUAL_VCPUS
,
1273 virDomainXMLOptionPtr
virTestGenericDomainXMLConfInit(void)
1275 return virDomainXMLOptionNew(&virTestGenericDomainDefParserConfig
,
1276 NULL
, NULL
, NULL
, NULL
);
1281 testCompareDomXML2XMLFiles(virCapsPtr caps
, virDomainXMLOptionPtr xmlopt
,
1282 const char *infile
, const char *outfile
, bool live
,
1283 unsigned int parseFlags
,
1284 testCompareDomXML2XMLResult expectResult
)
1286 char *actual
= NULL
;
1288 testCompareDomXML2XMLResult result
;
1289 virDomainDefPtr def
= NULL
;
1290 unsigned int parse_flags
= live
? 0 : VIR_DOMAIN_DEF_PARSE_INACTIVE
;
1291 unsigned int format_flags
= VIR_DOMAIN_DEF_FORMAT_SECURE
;
1293 parse_flags
|= parseFlags
;
1295 if (!virFileExists(infile
)) {
1296 VIR_TEST_DEBUG("Test input file '%s' is missing", infile
);
1301 format_flags
|= VIR_DOMAIN_DEF_FORMAT_INACTIVE
;
1303 if (!(def
= virDomainDefParseFile(infile
, caps
, xmlopt
, NULL
, parse_flags
))) {
1304 result
= TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE
;
1308 if (!virDomainDefCheckABIStability(def
, def
, xmlopt
)) {
1309 VIR_TEST_DEBUG("ABI stability check failed on %s", infile
);
1310 result
= TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_STABILITY
;
1314 if (!(actual
= virDomainDefFormat(def
, caps
, format_flags
))) {
1315 result
= TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_FORMAT
;
1319 if (virTestCompareToFile(actual
, outfile
) < 0) {
1320 result
= TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_COMPARE
;
1324 result
= TEST_COMPARE_DOM_XML2XML_RESULT_SUCCESS
;
1327 if (result
== expectResult
) {
1329 if (expectResult
!= TEST_COMPARE_DOM_XML2XML_RESULT_SUCCESS
) {
1330 VIR_TEST_DEBUG("Got expected failure code=%d msg=%s",
1331 result
, virGetLastErrorMessage());
1335 VIR_TEST_DEBUG("Expected result code=%d but received code=%d",
1336 expectResult
, result
);
1340 virDomainDefFree(def
);
1345 static int virtTestCounter
;
1346 static char virtTestCounterStr
[128];
1347 static char *virtTestCounterPrefixEndOffset
;
1351 * virTestCounterReset:
1352 * @prefix: name of the test group
1354 * Resets the counter and sets up the test group name to use with
1355 * virTestCounterNext(). This function is not thread safe.
1357 * Note: The buffer for the assembled message is 128 bytes long. Longer test
1358 * case names (including the number index) will be silently truncated.
1361 virTestCounterReset(const char *prefix
)
1363 virtTestCounter
= 0;
1365 ignore_value(virStrcpyStatic(virtTestCounterStr
, prefix
));
1366 virtTestCounterPrefixEndOffset
= strchrnul(virtTestCounterStr
, '\0');
1371 * virTestCounterNext:
1373 * This function is designed to ease test creation and reordering by adding
1374 * a way to do automagic test case numbering.
1376 * Returns string consisting of test name prefix configured via
1377 * virTestCounterReset() and a number that increments in every call of this
1378 * function. This function is not thread safe.
1380 * Note: The buffer for the assembled message is 128 bytes long. Longer test
1381 * case names (including the number index) will be silently truncated.
1384 *virTestCounterNext(void)
1386 size_t len
= ARRAY_CARDINALITY(virtTestCounterStr
);
1388 /* calculate length of the rest of the string */
1389 len
-= (virtTestCounterPrefixEndOffset
- virtTestCounterStr
);
1391 snprintf(virtTestCounterPrefixEndOffset
, len
, "%d", ++virtTestCounter
);
1393 return virtTestCounterStr
;