Add missing libxml2-tools dependency
[archive/platform/upstream/libvirt.git] / tests / testutils.c
1 /*
2  * testutils.c: basic test utils
3  *
4  * Copyright (C) 2005-2014 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  * Karel Zak <kzak@redhat.com>
21  */
22
23 #include <config.h>
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <sys/time.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <sys/wait.h>
31 #include <regex.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <fcntl.h>
35 #include <limits.h>
36 #include "testutils.h"
37 #include "internal.h"
38 #include "viralloc.h"
39 #include "virutil.h"
40 #include "virthread.h"
41 #include "virerror.h"
42 #include "virbuffer.h"
43 #include "virlog.h"
44 #include "vircommand.h"
45 #include "virrandom.h"
46 #include "dirname.h"
47 #include "virprocess.h"
48 #include "virstring.h"
49
50 #ifdef TEST_OOM
51 # ifdef TEST_OOM_TRACE
52 #  include <dlfcn.h>
53 #  include <execinfo.h>
54 # endif
55 #endif
56
57 #ifdef HAVE_PATHS_H
58 # include <paths.h>
59 #endif
60
61 #define VIR_FROM_THIS VIR_FROM_NONE
62
63 VIR_LOG_INIT("tests.testutils");
64
65 #define GETTIMEOFDAY(T) gettimeofday(T, NULL)
66 #define DIFF_MSEC(T, U)                                 \
67     ((((int) ((T)->tv_sec - (U)->tv_sec)) * 1000000.0 + \
68       ((int) ((T)->tv_usec - (U)->tv_usec))) / 1000.0)
69
70 #include "virfile.h"
71
72 static unsigned int testDebug = -1;
73 static unsigned int testVerbose = -1;
74 static unsigned int testExpensive = -1;
75
76 #ifdef TEST_OOM
77 static unsigned int testOOM = 0;
78 static unsigned int testOOMStart = -1;
79 static unsigned int testOOMEnd = -1;
80 static unsigned int testOOMTrace = 0;
81 # ifdef TEST_OOM_TRACE
82 void *testAllocStack[30];
83 int ntestAllocStack;
84 # endif
85 #endif
86 static bool testOOMActive = false;
87
88 static size_t testCounter = 0;
89 static size_t testStart = 0;
90 static size_t testEnd = 0;
91
92 char *progname;
93
94 bool virtTestOOMActive(void)
95 {
96     return testOOMActive;
97 }
98
99 #ifdef TEST_OOM_TRACE
100 static void virTestAllocHook(int nalloc ATTRIBUTE_UNUSED,
101                              void *opaque ATTRIBUTE_UNUSED)
102 {
103     ntestAllocStack = backtrace(testAllocStack, ARRAY_CARDINALITY(testAllocStack));
104 }
105 #endif
106
107 void virtTestResult(const char *name, int ret, const char *msg, ...)
108 {
109     va_list vargs;
110     va_start(vargs, msg);
111
112     if (testCounter == 0 && !virTestGetVerbose())
113         fprintf(stderr, "      ");
114
115     testCounter++;
116     if (virTestGetVerbose()) {
117         fprintf(stderr, "%3zu) %-60s ", testCounter, name);
118         if (ret == 0)
119             fprintf(stderr, "OK\n");
120         else {
121             fprintf(stderr, "FAILED\n");
122             if (msg) {
123                 char *str;
124                 if (virVasprintfQuiet(&str, msg, vargs) == 0) {
125                     fprintf(stderr, "%s", str);
126                     VIR_FREE(str);
127                 }
128             }
129         }
130     } else {
131         if (testCounter != 1 &&
132             !((testCounter-1) % 40)) {
133             fprintf(stderr, " %-3zu\n", (testCounter-1));
134             fprintf(stderr, "      ");
135         }
136         if (ret == 0)
137             fprintf(stderr, ".");
138         else
139             fprintf(stderr, "!");
140     }
141
142     va_end(vargs);
143 }
144
145 #ifdef TEST_OOM_TRACE
146 static void
147 virTestShowTrace(void)
148 {
149     size_t j;
150     for (j = 2; j < ntestAllocStack; j++) {
151         Dl_info info;
152         char *cmd;
153
154         dladdr(testAllocStack[j], &info);
155         if (info.dli_fname &&
156             strstr(info.dli_fname, ".so")) {
157             if (virAsprintf(&cmd, ADDR2LINE " -f -e %s %p",
158                             info.dli_fname,
159                             ((void*)((unsigned long long)testAllocStack[j]
160                                      - (unsigned long long)info.dli_fbase))) < 0)
161                 continue;
162         } else {
163             if (virAsprintf(&cmd, ADDR2LINE " -f -e %s %p",
164                             (char*)(info.dli_fname ? info.dli_fname : "<unknown>"),
165                             testAllocStack[j]) < 0)
166                 continue;
167         }
168         ignore_value(system(cmd));
169         VIR_FREE(cmd);
170     }
171 }
172 #endif
173
174 /*
175  * Runs test
176  *
177  * returns: -1 = error, 0 = success
178  */
179 int
180 virtTestRun(const char *title,
181             int (*body)(const void *data), const void *data)
182 {
183     int ret = 0;
184
185     if (testCounter == 0 && !virTestGetVerbose())
186         fprintf(stderr, "      ");
187
188     testCounter++;
189
190
191     /* Skip tests if out of range */
192     if ((testStart != 0) &&
193         (testCounter < testStart ||
194          testCounter > testEnd))
195         return 0;
196
197     if (virTestGetVerbose())
198         fprintf(stderr, "%2zu) %-65s ... ", testCounter, title);
199
200     virResetLastError();
201     ret = body(data);
202     virErrorPtr err = virGetLastError();
203     if (err) {
204         if (virTestGetVerbose() || virTestGetDebug())
205             virDispatchError(NULL);
206     }
207
208     if (virTestGetVerbose()) {
209         if (ret == 0)
210             fprintf(stderr, "OK\n");
211         else if (ret == EXIT_AM_SKIP)
212             fprintf(stderr, "SKIP\n");
213         else
214             fprintf(stderr, "FAILED\n");
215     } else {
216         if (testCounter != 1 &&
217             !((testCounter-1) % 40)) {
218             fprintf(stderr, " %-3zu\n", (testCounter-1));
219             fprintf(stderr, "      ");
220         }
221         if (ret == 0)
222                 fprintf(stderr, ".");
223         else if (ret == EXIT_AM_SKIP)
224             fprintf(stderr, "_");
225         else
226             fprintf(stderr, "!");
227     }
228
229 #ifdef TEST_OOM
230     if (testOOM && ret != EXIT_AM_SKIP) {
231         int nalloc;
232         int oomret;
233         int start, end;
234         size_t i;
235         virResetLastError();
236         virAllocTestInit();
237 # ifdef TEST_OOM_TRACE
238         virAllocTestHook(virTestAllocHook, NULL);
239 # endif
240         oomret = body(data);
241         nalloc = virAllocTestCount();
242         fprintf(stderr, "    Test OOM for nalloc=%d ", nalloc);
243         if (testOOMStart == -1 ||
244             testOOMEnd == -1) {
245             start = 0;
246             end = nalloc;
247         } else {
248             start = testOOMStart;
249             end = testOOMEnd + 1;
250         }
251         testOOMActive = true;
252         for (i = start; i < end; i++) {
253             bool missingFail = false;
254 # ifdef TEST_OOM_TRACE
255             memset(testAllocStack, 0, ARRAY_CARDINALITY(testAllocStack));
256             ntestAllocStack = 0;
257 # endif
258             virAllocTestOOM(i + 1, 1);
259             oomret = body(data);
260
261             /* fprintf() disabled because XML parsing APIs don't allow
262              * distinguish between element / attribute not present
263              * in the XML (which is non-fatal), vs OOM / malformed
264              * which should be fatal. Thus error reporting for
265              * optionally present XML is mostly broken.
266              */
267             if (oomret == 0) {
268                 missingFail = true;
269 # if 0
270                 fprintf(stderr, " alloc %zu failed but no err status\n", i + 1);
271 # endif
272             } else {
273                 virErrorPtr lerr = virGetLastError();
274                 if (!lerr) {
275 # if 0
276                     fprintf(stderr, " alloc %zu failed but no error report\n", i + 1);
277 # endif
278                     missingFail = true;
279                 }
280             }
281             if ((missingFail && testOOMTrace) || (testOOMTrace > 1)) {
282                 fprintf(stderr, "%s", "!");
283 # ifdef TEST_OOM_TRACE
284                 virTestShowTrace();
285 # endif
286                 ret = -1;
287             } else {
288                 fprintf(stderr, "%s", ".");
289             }
290         }
291         testOOMActive = false;
292         if (ret == 0)
293             fprintf(stderr, " OK\n");
294         else
295             fprintf(stderr, " FAILED\n");
296         virAllocTestInit();
297     }
298 #endif /* TEST_OOM */
299
300     return ret;
301 }
302
303 /* Allocate BUF to the size of FILE. Read FILE into buffer BUF.
304    Upon any failure, diagnose it and return -1, but don't bother trying
305    to preserve errno. Otherwise, return the number of bytes copied into BUF. */
306 int
307 virtTestLoadFile(const char *file, char **buf)
308 {
309     FILE *fp = fopen(file, "r");
310     struct stat st;
311     char *tmp;
312     int len, tmplen, buflen;
313
314     if (!fp) {
315         fprintf(stderr, "%s: failed to open: %s\n", file, strerror(errno));
316         return -1;
317     }
318
319     if (fstat(fileno(fp), &st) < 0) {
320         fprintf(stderr, "%s: failed to fstat: %s\n", file, strerror(errno));
321         VIR_FORCE_FCLOSE(fp);
322         return -1;
323     }
324
325     tmplen = buflen = st.st_size + 1;
326
327     if (VIR_ALLOC_N(*buf, buflen) < 0) {
328         VIR_FORCE_FCLOSE(fp);
329         return -1;
330     }
331
332     tmp = *buf;
333     (*buf)[0] = '\0';
334     if (st.st_size) {
335         /* read the file line by line */
336         while (fgets(tmp, tmplen, fp) != NULL) {
337             len = strlen(tmp);
338             /* stop on an empty line */
339             if (len == 0)
340                 break;
341             /* remove trailing backslash-newline pair */
342             if (len >= 2 && tmp[len-2] == '\\' && tmp[len-1] == '\n') {
343                 len -= 2;
344                 tmp[len] = '\0';
345             }
346             /* advance the temporary buffer pointer */
347             tmp += len;
348             tmplen -= len;
349         }
350         if (ferror(fp)) {
351             fprintf(stderr, "%s: read failed: %s\n", file, strerror(errno));
352             VIR_FORCE_FCLOSE(fp);
353             VIR_FREE(*buf);
354             return -1;
355         }
356     }
357
358     VIR_FORCE_FCLOSE(fp);
359     return strlen(*buf);
360 }
361
362 #ifndef WIN32
363 static
364 void virtTestCaptureProgramExecChild(const char *const argv[],
365                                      int pipefd)
366 {
367     size_t i;
368     int open_max;
369     int stdinfd = -1;
370     const char *const env[] = {
371         "LANG=C",
372 # if WITH_DRIVER_MODULES
373         "LIBVIRT_DRIVER_DIR=" TEST_DRIVER_DIR,
374 # endif
375         NULL
376     };
377
378     if ((stdinfd = open("/dev/null", O_RDONLY)) < 0)
379         goto cleanup;
380
381     open_max = sysconf(_SC_OPEN_MAX);
382     if (open_max < 0)
383         goto cleanup;
384
385     for (i = 0; i < open_max; i++) {
386         if (i != stdinfd &&
387             i != pipefd) {
388             int tmpfd;
389             tmpfd = i;
390             VIR_FORCE_CLOSE(tmpfd);
391         }
392     }
393
394     if (dup2(stdinfd, STDIN_FILENO) != STDIN_FILENO)
395         goto cleanup;
396     if (dup2(pipefd, STDOUT_FILENO) != STDOUT_FILENO)
397         goto cleanup;
398     if (dup2(pipefd, STDERR_FILENO) != STDERR_FILENO)
399         goto cleanup;
400
401     /* SUS is crazy here, hence the cast */
402     execve(argv[0], (char *const*)argv, (char *const*)env);
403
404  cleanup:
405     VIR_FORCE_CLOSE(stdinfd);
406 }
407
408 int
409 virtTestCaptureProgramOutput(const char *const argv[], char **buf, int maxlen)
410 {
411     int pipefd[2];
412     int len;
413
414     if (pipe(pipefd) < 0)
415         return -1;
416
417     pid_t pid = fork();
418     switch (pid) {
419     case 0:
420         VIR_FORCE_CLOSE(pipefd[0]);
421         virtTestCaptureProgramExecChild(argv, pipefd[1]);
422
423         VIR_FORCE_CLOSE(pipefd[1]);
424         _exit(EXIT_FAILURE);
425
426     case -1:
427         return -1;
428
429     default:
430         VIR_FORCE_CLOSE(pipefd[1]);
431         len = virFileReadLimFD(pipefd[0], maxlen, buf);
432         VIR_FORCE_CLOSE(pipefd[0]);
433         if (virProcessWait(pid, NULL, false) < 0)
434             return -1;
435
436         return len;
437     }
438 }
439 #else /* !WIN32 */
440 int
441 virtTestCaptureProgramOutput(const char *const argv[] ATTRIBUTE_UNUSED,
442                              char **buf ATTRIBUTE_UNUSED,
443                              int maxlen ATTRIBUTE_UNUSED)
444 {
445     return -1;
446 }
447 #endif /* !WIN32 */
448
449
450 /**
451  * @param stream: output stream write to differences to
452  * @param expect: expected output text
453  * @param actual: actual output text
454  *
455  * Display expected and actual output text, trimmed to
456  * first and last characters at which differences occur
457  */
458 int virtTestDifference(FILE *stream,
459                        const char *expect,
460                        const char *actual)
461 {
462     const char *expectStart;
463     const char *expectEnd;
464     const char *actualStart;
465     const char *actualEnd;
466
467     if (!expect)
468         expect = "";
469     if (!actual)
470         actual = "";
471
472     expectStart = expect;
473     expectEnd = expect + (strlen(expect)-1);
474     actualStart = actual;
475     actualEnd = actual + (strlen(actual)-1);
476
477     if (!virTestGetDebug())
478         return 0;
479
480     if (virTestGetDebug() < 2) {
481         /* Skip to first character where they differ */
482         while (*expectStart && *actualStart &&
483                *actualStart == *expectStart) {
484             actualStart++;
485             expectStart++;
486         }
487
488         /* Work backwards to last character where they differ */
489         while (actualEnd > actualStart &&
490                expectEnd > expectStart &&
491                *actualEnd == *expectEnd) {
492             actualEnd--;
493             expectEnd--;
494         }
495     }
496
497     /* Show the trimmed differences */
498     fprintf(stream, "\nOffset %d\nExpect [", (int) (expectStart - expect));
499     if ((expectEnd - expectStart + 1) &&
500         fwrite(expectStart, (expectEnd-expectStart+1), 1, stream) != 1)
501         return -1;
502     fprintf(stream, "]\n");
503     fprintf(stream, "Actual [");
504     if ((actualEnd - actualStart + 1) &&
505         fwrite(actualStart, (actualEnd-actualStart+1), 1, stream) != 1)
506         return -1;
507     fprintf(stream, "]\n");
508
509     /* Pad to line up with test name ... in virTestRun */
510     fprintf(stream, "                                                                      ... ");
511
512     return 0;
513 }
514
515 /**
516  * @param stream: output stream write to differences to
517  * @param expect: expected output text
518  * @param actual: actual output text
519  *
520  * Display expected and actual output text, trimmed to
521  * first and last characters at which differences occur
522  */
523 int virtTestDifferenceBin(FILE *stream,
524                           const char *expect,
525                           const char *actual,
526                           size_t length)
527 {
528     size_t start = 0, end = length;
529     ssize_t i;
530
531     if (!virTestGetDebug())
532         return 0;
533
534     if (virTestGetDebug() < 2) {
535         /* Skip to first character where they differ */
536         for (i = 0; i < length; i++) {
537             if (expect[i] != actual[i]) {
538                 start = i;
539                 break;
540             }
541         }
542
543         /* Work backwards to last character where they differ */
544         for (i = (length -1); i >= 0; i--) {
545             if (expect[i] != actual[i]) {
546                 end = i;
547                 break;
548             }
549         }
550     }
551     /* Round to nearest boundary of 4, except that last word can be short */
552     start -= (start % 4);
553     end += 4 - (end % 4);
554     if (end >= length)
555         end = length - 1;
556
557     /* Show the trimmed differences */
558     fprintf(stream, "\nExpect [ Region %d-%d", (int)start, (int)end);
559     for (i = start; i < end; i++) {
560         if ((i % 4) == 0)
561             fprintf(stream, "\n    ");
562         fprintf(stream, "0x%02x, ", ((int)expect[i])&0xff);
563     }
564     fprintf(stream, "]\n");
565     fprintf(stream, "Actual [ Region %d-%d", (int)start, (int)end);
566     for (i = start; i < end; i++) {
567         if ((i % 4) == 0)
568             fprintf(stream, "\n    ");
569         fprintf(stream, "0x%02x, ", ((int)actual[i])&0xff);
570     }
571     fprintf(stream, "]\n");
572
573     /* Pad to line up with test name ... in virTestRun */
574     fprintf(stream, "                                                                      ... ");
575
576     return 0;
577 }
578
579 static void
580 virtTestErrorFuncQuiet(void *data ATTRIBUTE_UNUSED,
581                        virErrorPtr err ATTRIBUTE_UNUSED)
582 { }
583
584
585 /* register an error handler in tests when using connections */
586 void
587 virtTestQuiesceLibvirtErrors(bool always)
588 {
589     if (always || !virTestGetVerbose())
590         virSetErrorFunc(NULL, virtTestErrorFuncQuiet);
591 }
592
593 struct virtTestLogData {
594     virBuffer buf;
595 };
596
597 static struct virtTestLogData testLog = { VIR_BUFFER_INITIALIZER };
598
599 static void
600 virtTestLogOutput(virLogSourcePtr source ATTRIBUTE_UNUSED,
601                   virLogPriority priority ATTRIBUTE_UNUSED,
602                   const char *filename ATTRIBUTE_UNUSED,
603                   int lineno ATTRIBUTE_UNUSED,
604                   const char *funcname ATTRIBUTE_UNUSED,
605                   const char *timestamp,
606                   virLogMetadataPtr metadata ATTRIBUTE_UNUSED,
607                   unsigned int flags,
608                   const char *rawstr ATTRIBUTE_UNUSED,
609                   const char *str,
610                   void *data)
611 {
612     struct virtTestLogData *log = data;
613     virCheckFlags(VIR_LOG_STACK_TRACE,);
614     if (!testOOMActive)
615         virBufferAsprintf(&log->buf, "%s: %s", timestamp, str);
616 }
617
618 static void
619 virtTestLogClose(void *data)
620 {
621     struct virtTestLogData *log = data;
622
623     virBufferFreeAndReset(&log->buf);
624 }
625
626 /* Return a malloc'd string (possibly with strlen of 0) of all data
627  * logged since the last call to this function, or NULL on failure.  */
628 char *
629 virtTestLogContentAndReset(void)
630 {
631     char *ret;
632
633     if (virBufferError(&testLog.buf))
634         return NULL;
635     ret = virBufferContentAndReset(&testLog.buf);
636     if (!ret)
637         ignore_value(VIR_STRDUP(ret, ""));
638     return ret;
639 }
640
641
642 static unsigned int
643 virTestGetFlag(const char *name)
644 {
645     char *flagStr;
646     unsigned int flag;
647
648     if ((flagStr = getenv(name)) == NULL)
649         return 0;
650
651     if (virStrToLong_ui(flagStr, NULL, 10, &flag) < 0)
652         return 0;
653
654     return flag;
655 }
656
657 unsigned int
658 virTestGetDebug(void)
659 {
660     if (testDebug == -1)
661         testDebug = virTestGetFlag("VIR_TEST_DEBUG");
662     return testDebug;
663 }
664
665 unsigned int
666 virTestGetVerbose(void)
667 {
668     if (testVerbose == -1)
669         testVerbose = virTestGetFlag("VIR_TEST_VERBOSE");
670     return testVerbose || virTestGetDebug();
671 }
672
673 unsigned int
674 virTestGetExpensive(void)
675 {
676     if (testExpensive == -1)
677         testExpensive = virTestGetFlag("VIR_TEST_EXPENSIVE");
678     return testExpensive;
679 }
680
681 int virtTestMain(int argc,
682                  char **argv,
683                  int (*func)(void))
684 {
685     int ret;
686     char *testRange = NULL;
687 #ifdef TEST_OOM
688     char *oomstr;
689 #endif
690
691     virFileActivateDirOverride(argv[0]);
692
693     if (!virFileExists(abs_srcdir))
694         return EXIT_AM_HARDFAIL;
695
696     progname = last_component(argv[0]);
697     if (STRPREFIX(progname, "lt-"))
698         progname += 3;
699     if (argc > 1) {
700         fprintf(stderr, "Usage: %s\n", argv[0]);
701         fputs("effective environment variables:\n"
702               "VIR_TEST_VERBOSE set to show names of individual tests\n"
703               "VIR_TEST_DEBUG set to show information for debugging failures\n",
704               stderr);
705         return EXIT_FAILURE;
706     }
707     fprintf(stderr, "TEST: %s\n", progname);
708
709     if (virThreadInitialize() < 0 ||
710         virErrorInitialize() < 0)
711         return EXIT_FAILURE;
712
713     virLogSetFromEnv();
714     if (!getenv("LIBVIRT_DEBUG") && !virLogGetNbOutputs()) {
715         if (virLogDefineOutput(virtTestLogOutput, virtTestLogClose, &testLog,
716                                VIR_LOG_DEBUG, VIR_LOG_TO_STDERR, NULL, 0) < 0)
717             return EXIT_FAILURE;
718     }
719
720     if ((testRange = getenv("VIR_TEST_RANGE")) != NULL) {
721         char *end = NULL;
722         unsigned int iv;
723         if (virStrToLong_ui(testRange, &end, 10, &iv) < 0) {
724             fprintf(stderr, "Cannot parse range %s\n", testRange);
725             return EXIT_FAILURE;
726         }
727         testStart = testEnd = iv;
728         if (end && *end) {
729             if (*end != '-') {
730                 fprintf(stderr, "Cannot parse range %s\n", testRange);
731                 return EXIT_FAILURE;
732             }
733             end++;
734             if (virStrToLong_ui(end, NULL, 10, &iv) < 0) {
735                 fprintf(stderr, "Cannot parse range %s\n", testRange);
736                 return EXIT_FAILURE;
737             }
738             testEnd = iv;
739
740             if (testEnd < testStart) {
741                 fprintf(stderr, "Test range end %zu must be >= %zu\n", testEnd, testStart);
742                 return EXIT_FAILURE;
743             }
744         }
745     }
746
747 #ifdef TEST_OOM
748     if ((oomstr = getenv("VIR_TEST_OOM")) != NULL) {
749         char *next;
750         if (testDebug == -1)
751             testDebug = 1;
752         testOOM = 1;
753         if (oomstr[0] != '\0' &&
754             oomstr[1] == ':') {
755             if (virStrToLong_ui(oomstr + 2, &next, 10, &testOOMStart) < 0) {
756                 fprintf(stderr, "Cannot parse range %s\n", oomstr);
757                 return EXIT_FAILURE;
758             }
759             if (*next == '\0') {
760                 testOOMEnd = testOOMStart;
761             } else {
762                 if (*next != '-') {
763                     fprintf(stderr, "Cannot parse range %s\n", oomstr);
764                     return EXIT_FAILURE;
765                 }
766                 if (virStrToLong_ui(next+1, NULL, 10, &testOOMEnd) < 0) {
767                     fprintf(stderr, "Cannot parse range %s\n", oomstr);
768                     return EXIT_FAILURE;
769                 }
770             }
771         } else {
772             testOOMStart = -1;
773             testOOMEnd = -1;
774         }
775     }
776
777 # ifdef TEST_OOM_TRACE
778     if ((oomstr = getenv("VIR_TEST_OOM_TRACE")) != NULL) {
779         if (virStrToLong_ui(oomstr, NULL, 10, &testOOMTrace) < 0) {
780             fprintf(stderr, "Cannot parse oom trace %s\n", oomstr);
781             return EXIT_FAILURE;
782         }
783     }
784 # else
785     if (getenv("VIR_TEST_OOM_TRACE")) {
786         fprintf(stderr, "%s", "OOM test tracing not enabled in this build\n");
787         return EXIT_FAILURE;
788     }
789 # endif
790 #else /* TEST_OOM */
791     if (getenv("VIR_TEST_OOM")) {
792         fprintf(stderr, "%s", "OOM testing not enabled in this build\n");
793         return EXIT_FAILURE;
794     }
795     if (getenv("VIR_TEST_OOM_TRACE")) {
796         fprintf(stderr, "%s", "OOM test tracing not enabled in this build\n");
797         return EXIT_FAILURE;
798     }
799 #endif /* TEST_OOM */
800
801     ret = (func)();
802
803     virResetLastError();
804     if (!virTestGetVerbose() && ret != EXIT_AM_SKIP) {
805         if (testCounter == 0 || testCounter % 40)
806             fprintf(stderr, "%*s", 40 - (int)(testCounter % 40), "");
807         fprintf(stderr, " %-3zu %s\n", testCounter, ret == 0 ? "OK" : "FAIL");
808     }
809     return ret;
810 }
811
812
813 int virtTestClearLineRegex(const char *pattern,
814                            char *str)
815 {
816     regex_t reg;
817     char *lineStart = str;
818     char *lineEnd = strchr(str, '\n');
819
820     if (regcomp(&reg, pattern, REG_EXTENDED | REG_NOSUB) != 0)
821         return -1;
822
823     while (lineStart) {
824         int ret;
825         if (lineEnd)
826             *lineEnd = '\0';
827
828
829         ret = regexec(&reg, lineStart, 0, NULL, 0);
830         //fprintf(stderr, "Match %d '%s' '%s'\n", ret, lineStart, pattern);
831         if (ret == 0) {
832             if (lineEnd) {
833                 memmove(lineStart, lineEnd + 1, strlen(lineEnd+1) + 1);
834                 /* Don't update lineStart - just iterate again on this
835                    location */
836                 lineEnd = strchr(lineStart, '\n');
837             } else {
838                 *lineStart = '\0';
839                 lineStart = NULL;
840             }
841         } else {
842             if (lineEnd) {
843                 *lineEnd = '\n';
844                 lineStart = lineEnd + 1;
845                 lineEnd = strchr(lineStart, '\n');
846             } else {
847                 lineStart = NULL;
848             }
849         }
850     }
851
852     regfree(&reg);
853
854     return 0;
855 }
856
857
858 /*
859  * @cmdset contains a list of command line args, eg
860  *
861  * "/usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp --destination-port 53 --jump ACCEPT
862  *  /usr/sbin/iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp --destination-port 53 --jump ACCEPT
863  *  /usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 --jump REJECT
864  *  /usr/sbin/iptables --table filter --insert FORWARD --out-interface virbr0 --jump REJECT
865  *  /usr/sbin/iptables --table filter --insert FORWARD --in-interface virbr0 --out-interface virbr0 --jump ACCEPT"
866  *
867  * And we're munging it in-place to strip the path component
868  * of the command line, to produce
869  *
870  * "iptables --table filter --insert INPUT --in-interface virbr0 --protocol tcp --destination-port 53 --jump ACCEPT
871  *  iptables --table filter --insert INPUT --in-interface virbr0 --protocol udp --destination-port 53 --jump ACCEPT
872  *  iptables --table filter --insert FORWARD --in-interface virbr0 --jump REJECT
873  *  iptables --table filter --insert FORWARD --out-interface virbr0 --jump REJECT
874  *  iptables --table filter --insert FORWARD --in-interface virbr0 --out-interface virbr0 --jump ACCEPT"
875  */
876 void virtTestClearCommandPath(char *cmdset)
877 {
878     size_t offset = 0;
879     char *lineStart = cmdset;
880     char *lineEnd = strchr(lineStart, '\n');
881
882     while (lineStart) {
883         char *dirsep;
884         char *movestart;
885         size_t movelen;
886         dirsep = strchr(lineStart, ' ');
887         if (dirsep) {
888             while (dirsep > lineStart && *dirsep != '/')
889                 dirsep--;
890             if (*dirsep == '/')
891                 dirsep++;
892             movestart = dirsep;
893         } else {
894             movestart = lineStart;
895         }
896         movelen = lineEnd ? lineEnd - movestart : strlen(movestart);
897
898         if (movelen) {
899             memmove(cmdset + offset, movestart, movelen + 1);
900             offset += movelen + 1;
901         }
902         lineStart = lineEnd ? lineEnd + 1 : NULL;
903         lineEnd = lineStart ? strchr(lineStart, '\n') : NULL;
904     }
905     cmdset[offset] = '\0';
906 }
907
908
909 virCapsPtr virTestGenericCapsInit(void)
910 {
911     virCapsPtr caps;
912     virCapsGuestPtr guest;
913
914     if ((caps = virCapabilitiesNew(VIR_ARCH_X86_64,
915                                    0, 0)) == NULL)
916         return NULL;
917
918     if ((guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_I686,
919                                          "/usr/bin/acme-virt", NULL,
920                                          0, NULL)) == NULL)
921         goto error;
922
923     if (!virCapabilitiesAddGuestDomain(guest, "test", NULL, NULL, 0, NULL))
924         goto error;
925
926
927     if ((guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_X86_64,
928                                          "/usr/bin/acme-virt", NULL,
929                                          0, NULL)) == NULL)
930         goto error;
931
932     if (!virCapabilitiesAddGuestDomain(guest, "test", NULL, NULL, 0, NULL))
933         goto error;
934
935
936     if (virTestGetDebug()) {
937         char *caps_str;
938
939         caps_str = virCapabilitiesFormatXML(caps);
940         if (!caps_str)
941             goto error;
942
943         fprintf(stderr, "Generic driver capabilities:\n%s", caps_str);
944
945         VIR_FREE(caps_str);
946     }
947
948     return caps;
949
950  error:
951     virObjectUnref(caps);
952     return NULL;
953 }
954
955 static virDomainDefParserConfig virTestGenericDomainDefParserConfig;
956 static virDomainXMLPrivateDataCallbacks virTestGenericPrivateDataCallbacks;
957
958 virDomainXMLOptionPtr virTestGenericDomainXMLConfInit(void)
959 {
960     return virDomainXMLOptionNew(&virTestGenericDomainDefParserConfig,
961                                  &virTestGenericPrivateDataCallbacks,
962                                  NULL);
963 }