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