1 /*
2 * testutils.c: basic test utils
3 *
4 * Copyright (C) 2005-2015 Red Hat, Inc.
5 *
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.
10 *
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.
15 *
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/>.
19 */
20
21 #include <config.h>
22
23 #include <stdarg.h>
24 #include <sys/time.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include "testutils.h"
30 #include "internal.h"
31 #include "viralloc.h"
32 #include "virthread.h"
33 #include "virerror.h"
34 #include "virbuffer.h"
35 #include "virlog.h"
36 #include "vircommand.h"
37 #include "virrandom.h"
38 #include "virprocess.h"
39 #include "virstring.h"
40
41 #define VIR_FROM_THIS VIR_FROM_NONE
42
43 VIR_LOG_INIT("tests.testutils");
44
45 #include "virbitmap.h"
46 #include "virfile.h"
47
48 static unsigned int testDebug = -1;
49 static unsigned int testVerbose = -1;
50 static unsigned int testExpensive = -1;
51 static unsigned int testRegenerate = -1;
52
53
54 static size_t testCounter;
55 static virBitmap *testBitmap;
56 static virBitmap *failedTests;
57
58 virArch virTestHostArch = VIR_ARCH_X86_64;
59
60 virArch
virArchFromHost(void)61 virArchFromHost(void)
62 {
63 return virTestHostArch;
64 }
65
66
virTestUseTerminalColors(void)67 static int virTestUseTerminalColors(void)
68 {
69 return isatty(STDOUT_FILENO);
70 }
71
72 static unsigned int
virTestGetFlag(const char * name)73 virTestGetFlag(const char *name)
74 {
75 char *flagStr;
76 unsigned int flag;
77
78 if ((flagStr = getenv(name)) == NULL)
79 return 0;
80
81 if (virStrToLong_ui(flagStr, NULL, 10, &flag) < 0)
82 return 0;
83
84 return flag;
85 }
86
87
88 /**
89 * virTestPropagateLibvirtError:
90 *
91 * In cases when a libvirt utility function which reports libvirt errors is
92 * used in the test suite outside of the virTestRun call and the failure of such
93 * a function would cause an test failure the error message reported by that
94 * function will not be propagated to the user as the error callback is not
95 * invoked.
96 *
97 * In cases when the error message may be beneficial in debugging this helper
98 * provides means to dispatch the errors including invocation of the error
99 * callback.
100 */
101 void
virTestPropagateLibvirtError(void)102 virTestPropagateLibvirtError(void)
103 {
104 if (virGetLastErrorCode() == VIR_ERR_OK)
105 return;
106
107 if (virTestGetVerbose() || virTestGetDebug())
108 virDispatchError(NULL);
109 }
110
111
112 /*
113 * Runs test
114 *
115 * returns: -1 = error, 0 = success
116 */
117 int
virTestRun(const char * title,int (* body)(const void * data),const void * data)118 virTestRun(const char *title,
119 int (*body)(const void *data), const void *data)
120 {
121 int ret = 0;
122
123 /* Some test are fragile about environ settings. If that's
124 * the case, don't poison it. */
125 if (getenv("VIR_TEST_MOCK_PROGNAME"))
126 g_setenv("VIR_TEST_MOCK_TESTNAME", title, TRUE);
127
128 if (testCounter == 0 && !virTestGetVerbose())
129 fprintf(stderr, " ");
130
131 testCounter++;
132
133
134 /* Skip tests if out of range */
135 if (testBitmap && !virBitmapIsBitSet(testBitmap, testCounter))
136 return 0;
137
138 if (virTestGetVerbose())
139 fprintf(stderr, "%2zu) %-65s ... ", testCounter, title);
140
141 virResetLastError();
142 ret = body(data);
143 virTestPropagateLibvirtError();
144
145 if (virTestGetVerbose()) {
146 if (ret == 0)
147 if (virTestUseTerminalColors())
148 fprintf(stderr, "\e[32mOK\e[0m\n"); /* green */
149 else
150 fprintf(stderr, "OK\n");
151 else if (ret == EXIT_AM_SKIP)
152 if (virTestUseTerminalColors())
153 fprintf(stderr, "\e[34m\e[1mSKIP\e[0m\n"); /* bold blue */
154 else
155 fprintf(stderr, "SKIP\n");
156 else
157 if (virTestUseTerminalColors())
158 fprintf(stderr, "\e[31m\e[1mFAILED\e[0m\n"); /* bold red */
159 else
160 fprintf(stderr, "FAILED\n");
161 } else {
162 if (testCounter != 1 &&
163 !((testCounter-1) % 40)) {
164 fprintf(stderr, " %-3zu\n", (testCounter-1));
165 fprintf(stderr, " ");
166 }
167 if (ret == 0)
168 fprintf(stderr, ".");
169 else if (ret == EXIT_AM_SKIP)
170 fprintf(stderr, "_");
171 else
172 fprintf(stderr, "!");
173 }
174
175 if (ret != 0 && ret != EXIT_AM_SKIP)
176 ignore_value(virBitmapSetBitExpand(failedTests, testCounter));
177
178 g_unsetenv("VIR_TEST_MOCK_TESTNAME");
179 return ret;
180 }
181
182
183 /*
184 * A wrapper for virTestRun that resets the log content before each run
185 * and sets ret to -1 on failure. On success, ret is untouched.
186 */
187 void
virTestRunLog(int * ret,const char * title,int (* body)(const void * data),const void * data)188 virTestRunLog(int *ret,
189 const char *title,
190 int (*body)(const void *data),
191 const void *data)
192 {
193 int rc;
194
195 g_free(virTestLogContentAndReset());
196
197 rc = virTestRun(title, body, data);
198
199 if (rc >= 0)
200 return;
201
202 *ret = -1;
203
204 if (virTestGetDebug()) {
205 g_autofree char *log = virTestLogContentAndReset();
206
207 if (strlen(log) > 0)
208 VIR_TEST_DEBUG("\n%s", log);
209 }
210 }
211
212
213 /**
214 * virTestLoadFile:
215 * @file: name of the file to load
216 * @buf: buffer to load the file into
217 *
218 * Allocates @buf to the size of FILE. Reads FILE into buffer BUF.
219 * Upon any failure, error is printed to stderr and -1 is returned. 'errno' is
220 * not preserved. On success 0 is returned. Caller is responsible for freeing
221 * @buf.
222 */
223 int
virTestLoadFile(const char * file,char ** buf)224 virTestLoadFile(const char *file, char **buf)
225 {
226 g_autoptr(FILE) fp = fopen(file, "r");
227 struct stat st;
228 char *tmp;
229 int len, tmplen, buflen;
230
231 if (!fp) {
232 fprintf(stderr, "%s: failed to open: %s\n", file, g_strerror(errno));
233 return -1;
234 }
235
236 if (fstat(fileno(fp), &st) < 0) {
237 fprintf(stderr, "%s: failed to fstat: %s\n", file, g_strerror(errno));
238 return -1;
239 }
240
241 tmplen = buflen = st.st_size + 1;
242
243 *buf = g_new0(char, buflen);
244
245 tmp = *buf;
246 (*buf)[0] = '\0';
247 if (st.st_size) {
248 /* read the file line by line */
249 while (fgets(tmp, tmplen, fp) != NULL) {
250 len = strlen(tmp);
251 /* stop on an empty line */
252 if (len == 0)
253 break;
254 /* remove trailing backslash-newline pair */
255 if (len >= 2 && tmp[len-2] == '\\' && tmp[len-1] == '\n') {
256 len -= 2;
257 tmp[len] = '\0';
258 }
259 /* advance the temporary buffer pointer */
260 tmp += len;
261 tmplen -= len;
262 }
263 if (ferror(fp)) {
264 fprintf(stderr, "%s: read failed: %s\n", file, g_strerror(errno));
265 VIR_FREE(*buf);
266 return -1;
267 }
268 }
269
270 return 0;
271 }
272
273
274 static char *
virTestLoadFileGetPath(const char * p,va_list ap)275 virTestLoadFileGetPath(const char *p,
276 va_list ap)
277 {
278 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
279 char *path = NULL;
280
281 virBufferAddLit(&buf, abs_srcdir "/");
282
283 if (p) {
284 virBufferAdd(&buf, p, -1);
285 virBufferStrcatVArgs(&buf, ap);
286 }
287
288 if (!(path = virBufferContentAndReset(&buf)))
289 VIR_TEST_VERBOSE("failed to format file path");
290
291 return path;
292 }
293
294
295 /**
296 * virTestLoadFilePath:
297 * @...: file name components terminated with a NULL
298 *
299 * Constructs the test file path from variable arguments and loads the file.
300 * 'abs_srcdir' is automatically prepended.
301 */
302 char *
virTestLoadFilePath(const char * p,...)303 virTestLoadFilePath(const char *p, ...)
304 {
305 g_autofree char *path = NULL;
306 char *ret = NULL;
307 va_list ap;
308
309 va_start(ap, p);
310
311 if (!(path = virTestLoadFileGetPath(p, ap)))
312 goto cleanup;
313
314 ignore_value(virTestLoadFile(path, &ret));
315
316 cleanup:
317 va_end(ap);
318
319 return ret;
320 }
321
322
323 /**
324 * virTestLoadFileJSON:
325 * @...: name components terminated with a NULL
326 *
327 * Constructs the test file path from variable arguments and loads and parses
328 * the JSON file. 'abs_srcdir' is automatically prepended to the path.
329 */
330 virJSONValue *
virTestLoadFileJSON(const char * p,...)331 virTestLoadFileJSON(const char *p, ...)
332 {
333 virJSONValue *ret = NULL;
334 g_autofree char *jsonstr = NULL;
335 g_autofree char *path = NULL;
336 va_list ap;
337
338 va_start(ap, p);
339
340 if (!(path = virTestLoadFileGetPath(p, ap)))
341 goto cleanup;
342
343 if (virFileReadAll(path, INT_MAX, &jsonstr) < 0)
344 goto cleanup;
345
346 if (!(ret = virJSONValueFromString(jsonstr)))
347 VIR_TEST_VERBOSE("failed to parse json from file '%s'", path);
348
349 cleanup:
350 va_end(ap);
351 return ret;
352 }
353
354
355 /**
356 * @param stream: output stream to write differences to
357 * @param expect: expected output text
358 * @param expectName: name designator of the expected text
359 * @param actual: actual output text
360 * @param actualName: name designator of the actual text
361 * @param regenerate: enable or disable regenerate functionality
362 * @param rewrap: enable or disable rewrapping when regenerating
363 *
364 * Display expected and actual output text, trimmed to first and last
365 * characters at which differences occur. Displays names of the text strings if
366 * non-NULL.
367 */
368 static int
virTestDifferenceFullInternal(FILE * stream,const char * expect,const char * expectName,const char * actual,const char * actualName,bool regenerate)369 virTestDifferenceFullInternal(FILE *stream,
370 const char *expect,
371 const char *expectName,
372 const char *actual,
373 const char *actualName,
374 bool regenerate)
375 {
376 const char *expectStart;
377 const char *expectEnd;
378 const char *actualStart;
379 const char *actualEnd;
380
381 if (!expect)
382 expect = "";
383 if (!actual)
384 actual = "";
385
386 expectStart = expect;
387 expectEnd = expect + (strlen(expect)-1);
388 actualStart = actual;
389 actualEnd = actual + (strlen(actual)-1);
390
391 if (expectName && regenerate && (virTestGetRegenerate() > 0)) {
392 if (virFileWriteStr(expectName, actual, 0666) < 0) {
393 virDispatchError(NULL);
394 return -1;
395 }
396 }
397
398 if (!virTestGetDebug())
399 return 0;
400
401 if (virTestGetDebug() < 2) {
402 /* Skip to first character where they differ */
403 while (*expectStart && *actualStart &&
404 *actualStart == *expectStart) {
405 actualStart++;
406 expectStart++;
407 }
408
409 /* Work backwards to last character where they differ */
410 while (actualEnd > actualStart &&
411 expectEnd > expectStart &&
412 *actualEnd == *expectEnd) {
413 actualEnd--;
414 expectEnd--;
415 }
416 }
417
418 /* Show the trimmed differences */
419 if (expectName)
420 fprintf(stream, "\nIn '%s':", expectName);
421 fprintf(stream, "\nOffset %d\nExpect [", (int) (expectStart - expect));
422 if ((expectEnd - expectStart + 1) &&
423 fwrite(expectStart, (expectEnd-expectStart+1), 1, stream) != 1)
424 return -1;
425 fprintf(stream, "]\n");
426 if (actualName)
427 fprintf(stream, "In '%s':\n", actualName);
428 fprintf(stream, "Actual [");
429 if ((actualEnd - actualStart + 1) &&
430 fwrite(actualStart, (actualEnd-actualStart+1), 1, stream) != 1)
431 return -1;
432 fprintf(stream, "]\n");
433
434 /* Pad to line up with test name ... in virTestRun */
435 fprintf(stream, " ... ");
436
437 return 0;
438 }
439
440 /**
441 * @param stream: output stream to write differences to
442 * @param expect: expected output text
443 * @param expectName: name designator of the expected text
444 * @param actual: actual output text
445 * @param actualName: name designator of the actual text
446 *
447 * Display expected and actual output text, trimmed to first and last
448 * characters at which differences occur. Displays names of the text strings if
449 * non-NULL. If VIR_TEST_REGENERATE_OUTPUT is used, this function will
450 * regenerate the expected file.
451 */
452 int
virTestDifferenceFull(FILE * stream,const char * expect,const char * expectName,const char * actual,const char * actualName)453 virTestDifferenceFull(FILE *stream,
454 const char *expect,
455 const char *expectName,
456 const char *actual,
457 const char *actualName)
458 {
459 return virTestDifferenceFullInternal(stream, expect, expectName,
460 actual, actualName, true);
461 }
462
463 /**
464 * @param stream: output stream to write differences to
465 * @param expect: expected output text
466 * @param expectName: name designator of the expected text
467 * @param actual: actual output text
468 * @param actualName: name designator of the actual text
469 *
470 * Display expected and actual output text, trimmed to first and last
471 * characters at which differences occur. Displays names of the text strings if
472 * non-NULL. If VIR_TEST_REGENERATE_OUTPUT is used, this function will not
473 * regenerate the expected file.
474 */
475 int
virTestDifferenceFullNoRegenerate(FILE * stream,const char * expect,const char * expectName,const char * actual,const char * actualName)476 virTestDifferenceFullNoRegenerate(FILE *stream,
477 const char *expect,
478 const char *expectName,
479 const char *actual,
480 const char *actualName)
481 {
482 return virTestDifferenceFullInternal(stream, expect, expectName,
483 actual, actualName, false);
484 }
485
486 /**
487 * @param stream: output stream to write differences to
488 * @param expect: expected output text
489 * @param actual: actual output text
490 *
491 * Display expected and actual output text, trimmed to
492 * first and last characters at which differences occur
493 */
494 int
virTestDifference(FILE * stream,const char * expect,const char * actual)495 virTestDifference(FILE *stream,
496 const char *expect,
497 const char *actual)
498 {
499 return virTestDifferenceFullNoRegenerate(stream,
500 expect, NULL,
501 actual, NULL);
502 }
503
504
505 /**
506 * @param stream: output stream to write differences to
507 * @param expect: expected output text
508 * @param actual: actual output text
509 *
510 * Display expected and actual output text, trimmed to
511 * first and last characters at which differences occur
512 */
virTestDifferenceBin(FILE * stream,const char * expect,const char * actual,size_t length)513 int virTestDifferenceBin(FILE *stream,
514 const char *expect,
515 const char *actual,
516 size_t length)
517 {
518 size_t start = 0, end = length;
519 ssize_t i;
520
521 if (!virTestGetDebug())
522 return 0;
523
524 if (virTestGetDebug() < 2) {
525 /* Skip to first character where they differ */
526 for (i = 0; i < length; i++) {
527 if (expect[i] != actual[i]) {
528 start = i;
529 break;
530 }
531 }
532
533 /* Work backwards to last character where they differ */
534 for (i = (length -1); i >= 0; i--) {
535 if (expect[i] != actual[i]) {
536 end = i;
537 break;
538 }
539 }
540 }
541 /* Round to nearest boundary of 4, except that last word can be short */
542 start -= (start % 4);
543 end += 4 - (end % 4);
544 if (end >= length)
545 end = length - 1;
546
547 /* Show the trimmed differences */
548 fprintf(stream, "\nExpect [ Region %d-%d", (int)start, (int)end);
549 for (i = start; i < end; i++) {
550 if ((i % 4) == 0)
551 fprintf(stream, "\n ");
552 fprintf(stream, "0x%02x, ", ((int)expect[i])&0xff);
553 }
554 fprintf(stream, "]\n");
555 fprintf(stream, "Actual [ Region %d-%d", (int)start, (int)end);
556 for (i = start; i < end; i++) {
557 if ((i % 4) == 0)
558 fprintf(stream, "\n ");
559 fprintf(stream, "0x%02x, ", ((int)actual[i])&0xff);
560 }
561 fprintf(stream, "]\n");
562
563 /* Pad to line up with test name ... in virTestRun */
564 fprintf(stream, " ... ");
565
566 return 0;
567 }
568
569 /*
570 * @param actual: String input content
571 * @param filename: File to compare @actual against
572 * @param unwrap: Remove '\\\n' sequences from file content before comparison
573 *
574 * If @actual is NULL, it's treated as an empty string.
575 */
576 int
virTestCompareToFileFull(const char * actual,const char * filename,bool unwrap)577 virTestCompareToFileFull(const char *actual,
578 const char *filename,
579 bool unwrap)
580 {
581 g_autofree char *filecontent = NULL;
582 g_autofree char *fixedcontent = NULL;
583 const char *cmpcontent = actual;
584
585 if (!cmpcontent)
586 cmpcontent = "";
587
588 if (unwrap) {
589 if (virTestLoadFile(filename, &filecontent) < 0 && !virTestGetRegenerate())
590 return -1;
591 } else {
592 if (virFileReadAll(filename, INT_MAX, &filecontent) < 0 && !virTestGetRegenerate())
593 return -1;
594 }
595
596 if (filecontent) {
597 size_t filecontentLen = strlen(filecontent);
598 size_t cmpcontentLen = strlen(cmpcontent);
599
600 if (filecontentLen > 0 &&
601 filecontent[filecontentLen - 1] == '\n' &&
602 (cmpcontentLen == 0 || cmpcontent[cmpcontentLen - 1] != '\n')) {
603 fixedcontent = g_strdup_printf("%s\n", cmpcontent);
604 cmpcontent = fixedcontent;
605 }
606 }
607
608 if (STRNEQ_NULLABLE(cmpcontent, filecontent)) {
609 virTestDifferenceFullInternal(stderr, filecontent, filename,
610 cmpcontent, NULL, true);
611 return -1;
612 }
613
614 return 0;
615 }
616
617
618 /*
619 * @param actual: String input content
620 * @param filename: File to compare @actual against
621 *
622 * If @actual is NULL, it's treated as an empty string.
623 */
624 int
virTestCompareToFile(const char * actual,const char * filename)625 virTestCompareToFile(const char *actual,
626 const char *filename)
627 {
628 return virTestCompareToFileFull(actual, filename, true);
629 }
630
631
632 int
virTestCompareToULL(unsigned long long expect,unsigned long long actual)633 virTestCompareToULL(unsigned long long expect,
634 unsigned long long actual)
635 {
636 g_autofree char *expectStr = NULL;
637 g_autofree char *actualStr = NULL;
638
639 expectStr = g_strdup_printf("%llu", expect);
640
641 actualStr = g_strdup_printf("%llu", actual);
642
643 return virTestCompareToString(expectStr, actualStr);
644 }
645
646 int
virTestCompareToString(const char * expect,const char * actual)647 virTestCompareToString(const char *expect,
648 const char *actual)
649 {
650 if (STRNEQ_NULLABLE(expect, actual)) {
651 virTestDifference(stderr, expect, actual);
652 return -1;
653 }
654
655 return 0;
656 }
657
658 static void
virTestErrorFuncQuiet(void * data G_GNUC_UNUSED,virErrorPtr err G_GNUC_UNUSED)659 virTestErrorFuncQuiet(void *data G_GNUC_UNUSED,
660 virErrorPtr err G_GNUC_UNUSED)
661 { }
662
663
664 /* register an error handler in tests when using connections */
665 void
virTestQuiesceLibvirtErrors(bool always)666 virTestQuiesceLibvirtErrors(bool always)
667 {
668 if (always || !virTestGetVerbose())
669 virSetErrorFunc(NULL, virTestErrorFuncQuiet);
670 }
671
672 struct virtTestLogData {
673 virBuffer buf;
674 };
675
676 static struct virtTestLogData testLog = { VIR_BUFFER_INITIALIZER };
677
678 static void
virtTestLogOutput(virLogSource * source G_GNUC_UNUSED,virLogPriority priority G_GNUC_UNUSED,const char * filename G_GNUC_UNUSED,int lineno G_GNUC_UNUSED,const char * funcname G_GNUC_UNUSED,const char * timestamp,struct _virLogMetadata * metadata G_GNUC_UNUSED,const char * rawstr G_GNUC_UNUSED,const char * str,void * data)679 virtTestLogOutput(virLogSource *source G_GNUC_UNUSED,
680 virLogPriority priority G_GNUC_UNUSED,
681 const char *filename G_GNUC_UNUSED,
682 int lineno G_GNUC_UNUSED,
683 const char *funcname G_GNUC_UNUSED,
684 const char *timestamp,
685 struct _virLogMetadata *metadata G_GNUC_UNUSED,
686 const char *rawstr G_GNUC_UNUSED,
687 const char *str,
688 void *data)
689 {
690 struct virtTestLogData *log = data;
691 virBufferAsprintf(&log->buf, "%s: %s", timestamp, str);
692 }
693
694 static void
virtTestLogClose(void * data)695 virtTestLogClose(void *data)
696 {
697 struct virtTestLogData *log = data;
698
699 virBufferFreeAndReset(&log->buf);
700 }
701
702 /* Return a malloc'd string (possibly with strlen of 0) of all data
703 * logged since the last call to this function, or NULL on failure. */
704 char *
virTestLogContentAndReset(void)705 virTestLogContentAndReset(void)
706 {
707 char *ret;
708
709 ret = virBufferContentAndReset(&testLog.buf);
710 if (!ret)
711 ret = g_strdup("");
712 return ret;
713 }
714
715
716 unsigned int
virTestGetDebug(void)717 virTestGetDebug(void)
718 {
719 if (testDebug == -1)
720 testDebug = virTestGetFlag("VIR_TEST_DEBUG");
721 return testDebug;
722 }
723
724 unsigned int
virTestGetVerbose(void)725 virTestGetVerbose(void)
726 {
727 if (testVerbose == -1)
728 testVerbose = virTestGetFlag("VIR_TEST_VERBOSE");
729 return testVerbose || virTestGetDebug();
730 }
731
732 unsigned int
virTestGetExpensive(void)733 virTestGetExpensive(void)
734 {
735 if (testExpensive == -1)
736 testExpensive = virTestGetFlag("VIR_TEST_EXPENSIVE");
737 return testExpensive;
738 }
739
740 unsigned int
virTestGetRegenerate(void)741 virTestGetRegenerate(void)
742 {
743 if (testRegenerate == -1)
744 testRegenerate = virTestGetFlag("VIR_TEST_REGENERATE_OUTPUT");
745 return testRegenerate;
746 }
747
748 static int
virTestSetEnvPath(void)749 virTestSetEnvPath(void)
750 {
751 const char *path = getenv("PATH");
752 g_autofree char *new_path = NULL;
753
754 if (path) {
755 if (strstr(path, abs_builddir) != path)
756 new_path = g_strdup_printf("%s:%s", abs_builddir, path);
757 } else {
758 new_path = g_strdup(abs_builddir);
759 }
760
761 if (new_path &&
762 g_setenv("PATH", new_path, TRUE) == FALSE)
763 return -1;
764
765 return 0;
766 }
767
virTestMain(int argc,char ** argv,int (* func)(void),...)768 int virTestMain(int argc,
769 char **argv,
770 int (*func)(void),
771 ...)
772 {
773 const char *lib;
774 va_list ap;
775 int ret;
776 char *testRange = NULL;
777 size_t noutputs = 0;
778 virLogOutput *output = NULL;
779 virLogOutput **outputs = NULL;
780 g_autofree char *progname = NULL;
781 g_autofree const char **preloads = NULL;
782 size_t npreloads = 0;
783 g_autofree char *mock = NULL;
784
785 if (getenv("VIR_TEST_FILE_ACCESS")) {
786 preloads = g_renew(const char *, preloads, npreloads + 2);
787 preloads[npreloads++] = VIR_TEST_MOCK("virtest");
788 preloads[npreloads] = NULL;
789 }
790
791 g_setenv("HOME", "/bad-test-used-env-home", TRUE);
792 g_setenv("XDG_RUNTIME_DIR", "/bad-test-used-env-xdg-runtime-dir", TRUE);
793
794 va_start(ap, func);
795 while ((lib = va_arg(ap, const char *))) {
796 if (!virFileIsExecutable(lib)) {
797 perror(lib);
798 va_end(ap);
799 return EXIT_FAILURE;
800 }
801
802 preloads = g_renew(const char *, preloads, npreloads + 2);
803 preloads[npreloads++] = lib;
804 preloads[npreloads] = NULL;
805 }
806 va_end(ap);
807
808 if (preloads) {
809 mock = g_strjoinv(":", (char **)preloads);
810 VIR_TEST_PRELOAD(mock);
811 }
812
813 progname = g_path_get_basename(argv[0]);
814
815 g_setenv("VIR_TEST_MOCK_PROGNAME", progname, TRUE);
816
817 virFileActivateDirOverrideForProg(argv[0]);
818
819 if (virTestSetEnvPath() < 0)
820 return EXIT_AM_HARDFAIL;
821
822 if (!virFileExists(abs_srcdir))
823 return EXIT_AM_HARDFAIL;
824
825 if (argc > 1) {
826 fprintf(stderr, "Usage: %s\n", argv[0]);
827 fputs("effective environment variables:\n"
828 "VIR_TEST_VERBOSE set to show names of individual tests\n"
829 "VIR_TEST_DEBUG set to show information for debugging failures",
830 stderr);
831 return EXIT_FAILURE;
832 }
833 fprintf(stderr, "TEST: %s\n", progname);
834
835 if (virErrorInitialize() < 0)
836 return EXIT_FAILURE;
837
838 virLogSetFromEnv();
839 if (!getenv("LIBVIRT_DEBUG") && !virLogGetNbOutputs()) {
840 if (!(output = virLogOutputNew(virtTestLogOutput, virtTestLogClose,
841 &testLog, VIR_LOG_DEBUG,
842 VIR_LOG_TO_STDERR, NULL)))
843 return EXIT_FAILURE;
844
845 VIR_APPEND_ELEMENT(outputs, noutputs, output);
846
847 if (virLogDefineOutputs(outputs, noutputs) < 0) {
848 virLogOutputListFree(outputs, noutputs);
849 return EXIT_FAILURE;
850 }
851 }
852
853 if ((testRange = getenv("VIR_TEST_RANGE")) != NULL) {
854 if (!(testBitmap = virBitmapParseUnlimited(testRange))) {
855 fprintf(stderr, "Cannot parse range %s\n", testRange);
856 return EXIT_FAILURE;
857 }
858 }
859
860 failedTests = virBitmapNew(1);
861
862 ret = (func)();
863
864 virResetLastError();
865 if (!virTestGetVerbose() && ret != EXIT_AM_SKIP) {
866 if (testCounter == 0 || testCounter % 40)
867 fprintf(stderr, "%*s", 40 - (int)(testCounter % 40), "");
868 fprintf(stderr, " %-3zu %s\n", testCounter, ret == 0 ? "OK" : "FAIL");
869 }
870
871 switch (ret) {
872 case EXIT_FAILURE:
873 case EXIT_SUCCESS:
874 case EXIT_AM_SKIP:
875 case EXIT_AM_HARDFAIL:
876 break;
877 default:
878 fprintf(stderr, "Test callback returned invalid value: %d\n", ret);
879 ret = EXIT_AM_HARDFAIL;
880 break;
881 }
882
883 if (ret == EXIT_FAILURE && !virBitmapIsAllClear(failedTests)) {
884 g_autofree char *failed = virBitmapFormat(failedTests);
885 fprintf(stderr, "Some tests failed. Run them using:\n");
886 fprintf(stderr, "VIR_TEST_DEBUG=1 VIR_TEST_RANGE=%s %s\n", failed, argv[0]);
887 }
888
889 virBitmapFree(testBitmap);
890 virBitmapFree(failedTests);
891 virLogReset();
892 return ret;
893 }
894
895
896 virCaps *
virTestGenericCapsInit(void)897 virTestGenericCapsInit(void)
898 {
899 g_autoptr(virCaps) caps = NULL;
900 virCapsGuest *guest;
901
902 if ((caps = virCapabilitiesNew(VIR_ARCH_X86_64,
903 false, false)) == NULL)
904 return NULL;
905
906 guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_I686,
907 "/usr/bin/acme-virt", NULL, 0, NULL);
908
909 virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_TEST,
910 NULL, NULL, 0, NULL);
911 virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_QEMU,
912 NULL, NULL, 0, NULL);
913 virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_KVM,
914 NULL, NULL, 0, NULL);
915
916 guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_HVM, VIR_ARCH_X86_64,
917 "/usr/bin/acme-virt", NULL, 0, NULL);
918
919 virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_TEST,
920 NULL, NULL, 0, NULL);
921 virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_QEMU,
922 NULL, NULL, 0, NULL);
923 virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_KVM,
924 NULL, NULL, 0, NULL);
925
926 if (virTestGetDebug() > 1) {
927 g_autofree char *caps_str = NULL;
928
929 caps_str = virCapabilitiesFormatXML(caps);
930 if (!caps_str)
931 return NULL;
932
933 VIR_TEST_DEBUG("Generic driver capabilities:\n%s", caps_str);
934 }
935
936 return g_steal_pointer(&caps);
937 }
938
939
940 #define MAX_CELLS 4
941 #define MAX_CPUS_IN_CELL 2
942 #define MAX_MEM_IN_CELL 2097152
943
944 /*
945 * Build NUMA topology with cell id starting from (0 + seq)
946 * for testing
947 */
948 virCapsHostNUMA *
virTestCapsBuildNUMATopology(int seq)949 virTestCapsBuildNUMATopology(int seq)
950 {
951 g_autoptr(virCapsHostNUMA) caps = virCapabilitiesHostNUMANew();
952 virCapsHostNUMACellCPU *cell_cpus = NULL;
953 int core_id, cell_id;
954 int id;
955
956 id = 0;
957 for (cell_id = 0; cell_id < MAX_CELLS; cell_id++) {
958 cell_cpus = g_new0(virCapsHostNUMACellCPU, MAX_CPUS_IN_CELL);
959
960 for (core_id = 0; core_id < MAX_CPUS_IN_CELL; core_id++) {
961 cell_cpus[core_id].id = id + core_id;
962 cell_cpus[core_id].socket_id = cell_id + seq;
963 cell_cpus[core_id].core_id = id + core_id;
964 cell_cpus[core_id].siblings = virBitmapNew(MAX_CPUS_IN_CELL);
965 ignore_value(virBitmapSetBit(cell_cpus[core_id].siblings, id));
966 }
967 id++;
968
969 virCapabilitiesHostNUMAAddCell(caps, cell_id + seq,
970 MAX_MEM_IN_CELL,
971 MAX_CPUS_IN_CELL, &cell_cpus,
972 0, NULL,
973 0, NULL,
974 NULL);
975
976 cell_cpus = NULL;
977 }
978
979 return g_steal_pointer(&caps);
980 }
981
982 static virDomainDefParserConfig virTestGenericDomainDefParserConfig = {
983 .features = VIR_DOMAIN_DEF_FEATURE_INDIVIDUAL_VCPUS,
984 };
985
virTestGenericDomainXMLConfInit(void)986 virDomainXMLOption *virTestGenericDomainXMLConfInit(void)
987 {
988 return virDomainXMLOptionNew(&virTestGenericDomainDefParserConfig,
989 NULL, NULL, NULL, NULL);
990 }
991
992
993 int
testCompareDomXML2XMLFiles(virCaps * caps G_GNUC_UNUSED,virDomainXMLOption * xmlopt,const char * infile,const char * outfile,bool live,unsigned int parseFlags,testCompareDomXML2XMLResult expectResult)994 testCompareDomXML2XMLFiles(virCaps *caps G_GNUC_UNUSED,
995 virDomainXMLOption *xmlopt,
996 const char *infile, const char *outfile, bool live,
997 unsigned int parseFlags,
998 testCompareDomXML2XMLResult expectResult)
999 {
1000 g_autofree char *actual = NULL;
1001 int ret = -1;
1002 testCompareDomXML2XMLResult result;
1003 g_autoptr(virDomainDef) def = NULL;
1004 unsigned int parse_flags = live ? 0 : VIR_DOMAIN_DEF_PARSE_INACTIVE;
1005 unsigned int format_flags = VIR_DOMAIN_DEF_FORMAT_SECURE;
1006
1007 parse_flags |= parseFlags;
1008
1009 if (!virFileExists(infile)) {
1010 VIR_TEST_DEBUG("Test input file '%s' is missing", infile);
1011 return -1;
1012 }
1013
1014 if (!live)
1015 format_flags |= VIR_DOMAIN_DEF_FORMAT_INACTIVE;
1016
1017 if (!(def = virDomainDefParseFile(infile, xmlopt, NULL, parse_flags))) {
1018 result = TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE;
1019 goto out;
1020 }
1021
1022 if (!virDomainDefCheckABIStability(def, def, xmlopt)) {
1023 VIR_TEST_DEBUG("ABI stability check failed on %s", infile);
1024 result = TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_STABILITY;
1025 goto out;
1026 }
1027
1028 if (!(actual = virDomainDefFormat(def, xmlopt, format_flags))) {
1029 result = TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_FORMAT;
1030 goto out;
1031 }
1032
1033 if (virTestCompareToFile(actual, outfile) < 0) {
1034 result = TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_COMPARE;
1035 goto out;
1036 }
1037
1038 result = TEST_COMPARE_DOM_XML2XML_RESULT_SUCCESS;
1039
1040 out:
1041 if (result == expectResult) {
1042 ret = 0;
1043 if (expectResult != TEST_COMPARE_DOM_XML2XML_RESULT_SUCCESS) {
1044 VIR_TEST_DEBUG("Got expected failure code=%d msg=%s",
1045 result, virGetLastErrorMessage());
1046 }
1047 } else {
1048 ret = -1;
1049 VIR_TEST_DEBUG("Expected result code=%d but received code=%d",
1050 expectResult, result);
1051 }
1052
1053 return ret;
1054 }
1055
1056
1057 static int virtTestCounter;
1058 static char virtTestCounterStr[128];
1059 static char *virtTestCounterPrefixEndOffset;
1060
1061
1062 /**
1063 * virTestCounterReset:
1064 * @prefix: name of the test group
1065 *
1066 * Resets the counter and sets up the test group name to use with
1067 * virTestCounterNext(). This function is not thread safe.
1068 *
1069 * Note: The buffer for the assembled message is 128 bytes long. Longer test
1070 * case names (including the number index) will be silently truncated.
1071 */
1072 void
virTestCounterReset(const char * prefix)1073 virTestCounterReset(const char *prefix)
1074 {
1075 virtTestCounter = 0;
1076
1077 ignore_value(virStrcpyStatic(virtTestCounterStr, prefix));
1078 virtTestCounterPrefixEndOffset = virtTestCounterStr + strlen(virtTestCounterStr);
1079 }
1080
1081
1082 /**
1083 * virTestCounterNext:
1084 *
1085 * This function is designed to ease test creation and reordering by adding
1086 * a way to do automagic test case numbering.
1087 *
1088 * Returns string consisting of test name prefix configured via
1089 * virTestCounterReset() and a number that increments in every call of this
1090 * function. This function is not thread safe.
1091 *
1092 * Note: The buffer for the assembled message is 128 bytes long. Longer test
1093 * case names (including the number index) will be silently truncated.
1094 */
1095 const char
virTestCounterNext(void)1096 *virTestCounterNext(void)
1097 {
1098 size_t len = G_N_ELEMENTS(virtTestCounterStr);
1099
1100 /* calculate length of the rest of the string */
1101 len -= (virtTestCounterPrefixEndOffset - virtTestCounterStr);
1102
1103 g_snprintf(virtTestCounterPrefixEndOffset, len, "%d", ++virtTestCounter);
1104
1105 return virtTestCounterStr;
1106 }
1107
1108
1109 /**
1110 * virTestStablePath:
1111 * @path: path to make stable
1112 *
1113 * If @path starts with the absolute source directory path, the prefix
1114 * is replaced with the string "ABS_SRCDIR" and similarly the build directory
1115 * is replaced by "ABS_BUILDDIR". This is useful when paths e.g. in output
1116 * test files need to be made stable.
1117 *
1118 * If @path is NULL the equivalent to NULLSTR(path) is returned.
1119 *
1120 * The caller is responsible for freeing the returned buffer.
1121 */
1122 char *
virTestStablePath(const char * path)1123 virTestStablePath(const char *path)
1124 {
1125 const char *tmp;
1126
1127 path = NULLSTR(path);
1128
1129 if ((tmp = STRSKIP(path, abs_srcdir)))
1130 return g_strdup_printf("ABS_SRCDIR%s", tmp);
1131
1132 if ((tmp = STRSKIP(path, abs_builddir)))
1133 return g_strdup_printf("ABS_BUILDDIR%s", tmp);
1134
1135 return g_strdup(path);
1136 }
1137
1138 #ifdef __linux__
1139 /**
1140 * virCreateAnonymousFile:
1141 * @data: a pointer to data to be written into a new file.
1142 * @len: the length of data to be written (in bytes).
1143 *
1144 * Create a fake fd, write initial data to it.
1145 *
1146 */
1147 int
virCreateAnonymousFile(const uint8_t * data,size_t len)1148 virCreateAnonymousFile(const uint8_t *data, size_t len)
1149 {
1150 int fd = -1;
1151 char path[] = abs_builddir "testutils-memfd-XXXXXX";
1152 /* A temp file is used since not all supported distributions support memfd. */
1153 if ((fd = g_mkstemp_full(path, O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR)) < 0) {
1154 return fd;
1155 }
1156 g_unlink(path);
1157
1158 if (safewrite(fd, data, len) != len) {
1159 VIR_TEST_DEBUG("%s: %s", "failed to write to an anonymous file",
1160 g_strerror(errno));
1161 goto cleanup;
1162 }
1163 return fd;
1164 cleanup:
1165 if (VIR_CLOSE(fd) < 0) {
1166 VIR_TEST_DEBUG("%s: %s", "failed to close an anonymous file",
1167 g_strerror(errno));
1168 }
1169 return -1;
1170 }
1171 #endif
1172