PageRenderTime 49ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/libvirt-0.9.11/tests/testutils.c

#
C | 761 lines | 597 code | 107 blank | 57 comment | 179 complexity | 2b44b4ea4dfb288e1bc85168f1fd4f3b MD5 | raw file
Possible License(s): LGPL-2.1
  1. /*
  2. * testutils.c: basic test utils
  3. *
  4. * Copyright (C) 2005-2012 Red Hat, Inc.
  5. *
  6. * See COPYING.LIB for the License of this software
  7. *
  8. * Karel Zak <kzak@redhat.com>
  9. */
  10. #include <config.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <sys/time.h>
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #ifndef WIN32
  17. # include <sys/wait.h>
  18. #endif
  19. #ifdef HAVE_REGEX_H
  20. # include <regex.h>
  21. #endif
  22. #include <unistd.h>
  23. #include <string.h>
  24. #include <fcntl.h>
  25. #include <limits.h>
  26. #include "testutils.h"
  27. #include "internal.h"
  28. #include "memory.h"
  29. #include "util.h"
  30. #include "threads.h"
  31. #include "virterror_internal.h"
  32. #include "buf.h"
  33. #include "logging.h"
  34. #include "command.h"
  35. #include "virrandom.h"
  36. #if TEST_OOM_TRACE
  37. # include <execinfo.h>
  38. #endif
  39. #ifdef HAVE_PATHS_H
  40. # include <paths.h>
  41. #endif
  42. #define GETTIMEOFDAY(T) gettimeofday(T, NULL)
  43. #define DIFF_MSEC(T, U) \
  44. ((((int) ((T)->tv_sec - (U)->tv_sec)) * 1000000.0 + \
  45. ((int) ((T)->tv_usec - (U)->tv_usec))) / 1000.0)
  46. #include "virfile.h"
  47. static unsigned int testDebug = -1;
  48. static unsigned int testVerbose = -1;
  49. static unsigned int testOOM = 0;
  50. static unsigned int testCounter = 0;
  51. char *progname;
  52. char *abs_srcdir;
  53. double
  54. virtTestCountAverage(double *items, int nitems)
  55. {
  56. long double sum = 0;
  57. int i;
  58. for (i=1; i < nitems; i++)
  59. sum += items[i];
  60. return (double) (sum / nitems);
  61. }
  62. ATTRIBUTE_FMT_PRINTF(3,4)
  63. void virtTestResult(const char *name, int ret, const char *msg, ...)
  64. {
  65. va_list vargs;
  66. va_start(vargs, msg);
  67. if (testCounter == 0 && !virTestGetVerbose())
  68. fprintf(stderr, " ");
  69. testCounter++;
  70. if (virTestGetVerbose()) {
  71. fprintf(stderr, "%3d) %-60s ", testCounter, name);
  72. if (ret == 0)
  73. fprintf(stderr, "OK\n");
  74. else {
  75. fprintf(stderr, "FAILED\n");
  76. if (msg) {
  77. vfprintf(stderr, msg, vargs);
  78. }
  79. }
  80. } else {
  81. if (testCounter != 1 &&
  82. !((testCounter-1) % 40)) {
  83. fprintf(stderr, " %-3d\n", (testCounter-1));
  84. fprintf(stderr, " ");
  85. }
  86. if (ret == 0)
  87. fprintf(stderr, ".");
  88. else
  89. fprintf(stderr, "!");
  90. }
  91. va_end(vargs);
  92. }
  93. /*
  94. * Runs test and count average time (if the nloops is grater than 1)
  95. *
  96. * returns: -1 = error, 0 = success
  97. */
  98. int
  99. virtTestRun(const char *title, int nloops, int (*body)(const void *data), const void *data)
  100. {
  101. int i, ret = 0;
  102. double *ts = NULL;
  103. if (testCounter == 0 && !virTestGetVerbose())
  104. fprintf(stderr, " ");
  105. testCounter++;
  106. if (testOOM < 2) {
  107. if (virTestGetVerbose())
  108. fprintf(stderr, "%2d) %-65s ... ", testCounter, title);
  109. }
  110. if (nloops > 1 && (VIR_ALLOC_N(ts, nloops) < 0))
  111. return -1;
  112. for (i=0; i < nloops; i++) {
  113. struct timeval before, after;
  114. if (ts)
  115. GETTIMEOFDAY(&before);
  116. virResetLastError();
  117. ret = body(data);
  118. virErrorPtr err = virGetLastError();
  119. if (err) {
  120. if (virTestGetVerbose() || virTestGetDebug())
  121. virDispatchError(NULL);
  122. }
  123. if (ret != 0) {
  124. break;
  125. }
  126. if (ts) {
  127. GETTIMEOFDAY(&after);
  128. ts[i] = DIFF_MSEC(&after, &before);
  129. }
  130. }
  131. if (testOOM < 2) {
  132. if (virTestGetVerbose()) {
  133. if (ret == 0 && ts)
  134. fprintf(stderr, "OK [%.5f ms]\n",
  135. virtTestCountAverage(ts, nloops));
  136. else if (ret == 0)
  137. fprintf(stderr, "OK\n");
  138. else if (ret == EXIT_AM_SKIP)
  139. fprintf(stderr, "SKIP\n");
  140. else
  141. fprintf(stderr, "FAILED\n");
  142. } else {
  143. if (testCounter != 1 &&
  144. !((testCounter-1) % 40)) {
  145. fprintf(stderr, " %-3d\n", (testCounter-1));
  146. fprintf(stderr, " ");
  147. }
  148. if (ret == 0)
  149. fprintf(stderr, ".");
  150. else if (ret == EXIT_AM_SKIP)
  151. fprintf(stderr, "_");
  152. else
  153. fprintf(stderr, "!");
  154. }
  155. }
  156. VIR_FREE(ts);
  157. return ret;
  158. }
  159. /* Allocate BUF to the size of FILE. Read FILE into buffer BUF.
  160. Upon any failure, diagnose it and return -1, but don't bother trying
  161. to preserve errno. Otherwise, return the number of bytes copied into BUF. */
  162. int
  163. virtTestLoadFile(const char *file, char **buf)
  164. {
  165. FILE *fp = fopen(file, "r");
  166. struct stat st;
  167. char *tmp;
  168. int len, tmplen, buflen;
  169. if (!fp) {
  170. fprintf (stderr, "%s: failed to open: %s\n", file, strerror(errno));
  171. return -1;
  172. }
  173. if (fstat(fileno(fp), &st) < 0) {
  174. fprintf (stderr, "%s: failed to fstat: %s\n", file, strerror(errno));
  175. VIR_FORCE_FCLOSE(fp);
  176. return -1;
  177. }
  178. tmplen = buflen = st.st_size + 1;
  179. if (VIR_ALLOC_N(*buf, buflen) < 0) {
  180. fprintf (stderr, "%s: larger than available memory (> %d)\n", file, buflen);
  181. VIR_FORCE_FCLOSE(fp);
  182. return -1;
  183. }
  184. tmp = *buf;
  185. (*buf)[0] = '\0';
  186. if (st.st_size) {
  187. /* read the file line by line */
  188. while (fgets(tmp, tmplen, fp) != NULL) {
  189. len = strlen(tmp);
  190. /* stop on an empty line */
  191. if (len == 0)
  192. break;
  193. /* remove trailing backslash-newline pair */
  194. if (len >= 2 && tmp[len-2] == '\\' && tmp[len-1] == '\n') {
  195. len -= 2;
  196. tmp[len] = '\0';
  197. }
  198. /* advance the temporary buffer pointer */
  199. tmp += len;
  200. tmplen -= len;
  201. }
  202. if (ferror(fp)) {
  203. fprintf (stderr, "%s: read failed: %s\n", file, strerror(errno));
  204. VIR_FORCE_FCLOSE(fp);
  205. VIR_FREE(*buf);
  206. return -1;
  207. }
  208. }
  209. VIR_FORCE_FCLOSE(fp);
  210. return strlen(*buf);
  211. }
  212. #ifndef WIN32
  213. static
  214. void virtTestCaptureProgramExecChild(const char *const argv[],
  215. int pipefd) {
  216. int i;
  217. int open_max;
  218. int stdinfd = -1;
  219. const char *const env[] = {
  220. "LANG=C",
  221. # if WITH_DRIVER_MODULES
  222. "LIBVIRT_DRIVER_DIR=" TEST_DRIVER_DIR,
  223. # endif
  224. NULL
  225. };
  226. if ((stdinfd = open("/dev/null", O_RDONLY)) < 0)
  227. goto cleanup;
  228. open_max = sysconf (_SC_OPEN_MAX);
  229. for (i = 0; i < open_max; i++) {
  230. if (i != stdinfd &&
  231. i != pipefd) {
  232. int tmpfd = i;
  233. VIR_FORCE_CLOSE(tmpfd);
  234. }
  235. }
  236. if (dup2(stdinfd, STDIN_FILENO) != STDIN_FILENO)
  237. goto cleanup;
  238. if (dup2(pipefd, STDOUT_FILENO) != STDOUT_FILENO)
  239. goto cleanup;
  240. if (dup2(pipefd, STDERR_FILENO) != STDERR_FILENO)
  241. goto cleanup;
  242. /* SUS is crazy here, hence the cast */
  243. execve(argv[0], (char *const*)argv, (char *const*)env);
  244. cleanup:
  245. VIR_FORCE_CLOSE(stdinfd);
  246. }
  247. int
  248. virtTestCaptureProgramOutput(const char *const argv[], char **buf, int maxlen)
  249. {
  250. int pipefd[2];
  251. int len;
  252. if (pipe(pipefd) < 0)
  253. return -1;
  254. pid_t pid = fork();
  255. switch (pid) {
  256. case 0:
  257. VIR_FORCE_CLOSE(pipefd[0]);
  258. virtTestCaptureProgramExecChild(argv, pipefd[1]);
  259. VIR_FORCE_CLOSE(pipefd[1]);
  260. _exit(1);
  261. case -1:
  262. return -1;
  263. default:
  264. VIR_FORCE_CLOSE(pipefd[1]);
  265. len = virFileReadLimFD(pipefd[0], maxlen, buf);
  266. VIR_FORCE_CLOSE(pipefd[0]);
  267. if (virPidWait(pid, NULL) < 0)
  268. return -1;
  269. return len;
  270. }
  271. }
  272. #else /* !WIN32 */
  273. int
  274. virtTestCaptureProgramOutput(const char *const argv[] ATTRIBUTE_UNUSED,
  275. char **buf ATTRIBUTE_UNUSED,
  276. int maxlen ATTRIBUTE_UNUSED)
  277. {
  278. return -1;
  279. }
  280. #endif /* !WIN32 */
  281. /**
  282. * @param stream: output stream write to differences to
  283. * @param expect: expected output text
  284. * @param actual: actual output text
  285. *
  286. * Display expected and actual output text, trimmed to
  287. * first and last characters at which differences occur
  288. */
  289. int virtTestDifference(FILE *stream,
  290. const char *expect,
  291. const char *actual)
  292. {
  293. const char *expectStart = expect;
  294. const char *expectEnd = expect + (strlen(expect)-1);
  295. const char *actualStart = actual;
  296. const char *actualEnd = actual + (strlen(actual)-1);
  297. if (!virTestGetDebug())
  298. return 0;
  299. if (virTestGetDebug() < 2) {
  300. /* Skip to first character where they differ */
  301. while (*expectStart && *actualStart &&
  302. *actualStart == *expectStart) {
  303. actualStart++;
  304. expectStart++;
  305. }
  306. /* Work backwards to last character where they differ */
  307. while (actualEnd > actualStart &&
  308. expectEnd > expectStart &&
  309. *actualEnd == *expectEnd) {
  310. actualEnd--;
  311. expectEnd--;
  312. }
  313. }
  314. /* Show the trimmed differences */
  315. fprintf(stream, "\nOffset %d\nExpect [", (int) (expectStart - expect));
  316. if ((expectEnd - expectStart + 1) &&
  317. fwrite(expectStart, (expectEnd-expectStart+1), 1, stream) != 1)
  318. return -1;
  319. fprintf(stream, "]\n");
  320. fprintf(stream, "Actual [");
  321. if ((actualEnd - actualStart + 1) &&
  322. fwrite(actualStart, (actualEnd-actualStart+1), 1, stream) != 1)
  323. return -1;
  324. fprintf(stream, "]\n");
  325. /* Pad to line up with test name ... in virTestRun */
  326. fprintf(stream, " ... ");
  327. return 0;
  328. }
  329. /**
  330. * @param stream: output stream write to differences to
  331. * @param expect: expected output text
  332. * @param actual: actual output text
  333. *
  334. * Display expected and actual output text, trimmed to
  335. * first and last characters at which differences occur
  336. */
  337. int virtTestDifferenceBin(FILE *stream,
  338. const char *expect,
  339. const char *actual,
  340. size_t length)
  341. {
  342. size_t start = 0, end = length;
  343. ssize_t i;
  344. if (!virTestGetDebug())
  345. return 0;
  346. if (virTestGetDebug() < 2) {
  347. /* Skip to first character where they differ */
  348. for (i = 0 ; i < length ; i++) {
  349. if (expect[i] != actual[i]) {
  350. start = i;
  351. break;
  352. }
  353. }
  354. /* Work backwards to last character where they differ */
  355. for (i = (length -1) ; i >= 0 ; i--) {
  356. if (expect[i] != actual[i]) {
  357. end = i;
  358. break;
  359. }
  360. }
  361. }
  362. /* Round to nearest boundary of 4, except that last word can be short */
  363. start -= (start % 4);
  364. end += 4 - (end % 4);
  365. if (end >= length)
  366. end = length - 1;
  367. /* Show the trimmed differences */
  368. fprintf(stream, "\nExpect [ Region %d-%d", (int)start, (int)end);
  369. for (i = start; i < end ; i++) {
  370. if ((i % 4) == 0)
  371. fprintf(stream, "\n ");
  372. fprintf(stream, "0x%02x, ", ((int)expect[i])&0xff);
  373. }
  374. fprintf(stream, "]\n");
  375. fprintf(stream, "Actual [ Region %d-%d", (int)start, (int)end);
  376. for (i = start; i < end ; i++) {
  377. if ((i % 4) == 0)
  378. fprintf(stream, "\n ");
  379. fprintf(stream, "0x%02x, ", ((int)actual[i])&0xff);
  380. }
  381. fprintf(stream, "]\n");
  382. /* Pad to line up with test name ... in virTestRun */
  383. fprintf(stream, " ... ");
  384. return 0;
  385. }
  386. #if TEST_OOM
  387. static void
  388. virtTestErrorFuncQuiet(void *data ATTRIBUTE_UNUSED,
  389. virErrorPtr err ATTRIBUTE_UNUSED)
  390. { }
  391. #endif
  392. struct virtTestLogData {
  393. virBuffer buf;
  394. };
  395. static struct virtTestLogData testLog = { VIR_BUFFER_INITIALIZER };
  396. static int
  397. virtTestLogOutput(const char *category ATTRIBUTE_UNUSED,
  398. int priority ATTRIBUTE_UNUSED,
  399. const char *funcname ATTRIBUTE_UNUSED,
  400. long long lineno ATTRIBUTE_UNUSED,
  401. const char *timestamp,
  402. const char *str,
  403. void *data)
  404. {
  405. struct virtTestLogData *log = data;
  406. virBufferAsprintf(&log->buf, "%s: %s", timestamp, str);
  407. return strlen(timestamp) + 2 + strlen(str);
  408. }
  409. static void
  410. virtTestLogClose(void *data)
  411. {
  412. struct virtTestLogData *log = data;
  413. virBufferFreeAndReset(&log->buf);
  414. }
  415. /* Return a malloc'd string (possibly with strlen of 0) of all data
  416. * logged since the last call to this function, or NULL on failure. */
  417. char *
  418. virtTestLogContentAndReset(void)
  419. {
  420. char *ret;
  421. if (virBufferError(&testLog.buf))
  422. return NULL;
  423. ret = virBufferContentAndReset(&testLog.buf);
  424. return ret ? ret : strdup("");
  425. }
  426. #if TEST_OOM_TRACE
  427. static void
  428. virtTestErrorHook(int n, void *data ATTRIBUTE_UNUSED)
  429. {
  430. void *trace[30];
  431. int ntrace = ARRAY_CARDINALITY(trace);
  432. int i;
  433. char **symbols = NULL;
  434. ntrace = backtrace(trace, ntrace);
  435. symbols = backtrace_symbols(trace, ntrace);
  436. if (symbols) {
  437. fprintf(stderr, "Failing allocation %d at:\n", n);
  438. for (i = 0 ; i < ntrace ; i++) {
  439. if (symbols[i])
  440. fprintf(stderr, " TRACE: %s\n", symbols[i]);
  441. }
  442. VIR_FREE(symbols);
  443. }
  444. }
  445. #endif
  446. static unsigned int
  447. virTestGetFlag(const char *name) {
  448. char *flagStr;
  449. unsigned int flag;
  450. if ((flagStr = getenv(name)) == NULL)
  451. return 0;
  452. if (virStrToLong_ui(flagStr, NULL, 10, &flag) < 0)
  453. return 0;
  454. return flag;
  455. }
  456. unsigned int
  457. virTestGetDebug(void) {
  458. if (testDebug == -1)
  459. testDebug = virTestGetFlag("VIR_TEST_DEBUG");
  460. return testDebug;
  461. }
  462. unsigned int
  463. virTestGetVerbose(void) {
  464. if (testVerbose == -1)
  465. testVerbose = virTestGetFlag("VIR_TEST_VERBOSE");
  466. return testVerbose || virTestGetDebug();
  467. }
  468. int virtTestMain(int argc,
  469. char **argv,
  470. int (*func)(void))
  471. {
  472. int ret;
  473. bool abs_srcdir_cleanup = false;
  474. #if TEST_OOM
  475. int approxAlloc = 0;
  476. int n;
  477. char *oomStr = NULL;
  478. int oomCount;
  479. int mp = 0;
  480. pid_t *workers;
  481. int worker = 0;
  482. #endif
  483. abs_srcdir = getenv("abs_srcdir");
  484. if (!abs_srcdir) {
  485. abs_srcdir = getcwd(NULL, 0);
  486. abs_srcdir_cleanup = true;
  487. }
  488. if (!abs_srcdir)
  489. exit(EXIT_AM_HARDFAIL);
  490. progname = argv[0];
  491. if (STRPREFIX(progname, "./"))
  492. progname += 2;
  493. if (argc > 1) {
  494. fprintf(stderr, "Usage: %s\n", argv[0]);
  495. return EXIT_FAILURE;
  496. }
  497. fprintf(stderr, "TEST: %s\n", progname);
  498. if (virThreadInitialize() < 0 ||
  499. virErrorInitialize() < 0 ||
  500. virRandomInitialize(time(NULL) ^ getpid()))
  501. return 1;
  502. virLogSetFromEnv();
  503. if (!getenv("LIBVIRT_DEBUG") && !virLogGetNbOutputs()) {
  504. if (virLogDefineOutput(virtTestLogOutput, virtTestLogClose, &testLog,
  505. 0, 0, NULL, 0) < 0)
  506. return 1;
  507. }
  508. #if TEST_OOM
  509. if ((oomStr = getenv("VIR_TEST_OOM")) != NULL) {
  510. if (virStrToLong_i(oomStr, NULL, 10, &oomCount) < 0)
  511. oomCount = 0;
  512. if (oomCount < 0)
  513. oomCount = 0;
  514. if (oomCount)
  515. testOOM = 1;
  516. }
  517. if (getenv("VIR_TEST_MP") != NULL) {
  518. mp = sysconf(_SC_NPROCESSORS_ONLN);
  519. fprintf(stderr, "Using %d worker processes\n", mp);
  520. if (VIR_ALLOC_N(workers, mp) < 0) {
  521. ret = EXIT_FAILURE;
  522. goto cleanup;
  523. }
  524. }
  525. /* Run once to prime any static allocations & ensure it passes */
  526. ret = (func)();
  527. if (ret != EXIT_SUCCESS)
  528. goto cleanup;
  529. # if TEST_OOM_TRACE
  530. if (virTestGetDebug())
  531. virAllocTestHook(virtTestErrorHook, NULL);
  532. # endif
  533. if (testOOM) {
  534. /* Makes next test runs quiet... */
  535. testOOM++;
  536. virSetErrorFunc(NULL, virtTestErrorFuncQuiet);
  537. virAllocTestInit();
  538. /* Run again to count allocs, and ensure it passes :-) */
  539. ret = (func)();
  540. if (ret != EXIT_SUCCESS)
  541. goto cleanup;
  542. approxAlloc = virAllocTestCount();
  543. testCounter++;
  544. if (virTestGetDebug())
  545. fprintf(stderr, "%d) OOM...\n", testCounter);
  546. else
  547. fprintf(stderr, "%d) OOM of %d allocs ", testCounter, approxAlloc);
  548. if (mp) {
  549. int i;
  550. for (i = 0 ; i < mp ; i++) {
  551. workers[i] = fork();
  552. if (workers[i] == 0) {
  553. worker = i + 1;
  554. break;
  555. }
  556. }
  557. }
  558. /* Run once for each alloc, failing a different one
  559. and validating that the test case failed */
  560. for (n = 0; n < approxAlloc && (!mp || worker) ; n++) {
  561. if (mp &&
  562. (n % mp) != (worker - 1))
  563. continue;
  564. if (!virTestGetDebug()) {
  565. if (mp)
  566. fprintf(stderr, "%d", worker);
  567. else
  568. fprintf(stderr, ".");
  569. fflush(stderr);
  570. }
  571. virAllocTestOOM(n+1, oomCount);
  572. if (((func)()) != EXIT_FAILURE) {
  573. ret = EXIT_FAILURE;
  574. break;
  575. }
  576. }
  577. if (mp) {
  578. if (worker) {
  579. _exit(ret);
  580. } else {
  581. int i, status;
  582. for (i = 0 ; i < mp ; i++) {
  583. if (virPidWait(workers[i], NULL) < 0)
  584. ret = EXIT_FAILURE;
  585. }
  586. VIR_FREE(workers);
  587. }
  588. }
  589. if (virTestGetDebug())
  590. fprintf(stderr, " ... OOM of %d allocs", approxAlloc);
  591. if (ret == EXIT_SUCCESS)
  592. fprintf(stderr, " OK\n");
  593. else
  594. fprintf(stderr, " FAILED\n");
  595. }
  596. cleanup:
  597. #else
  598. ret = (func)();
  599. #endif
  600. if (abs_srcdir_cleanup)
  601. VIR_FREE(abs_srcdir);
  602. virResetLastError();
  603. if (!virTestGetVerbose() && ret != EXIT_AM_SKIP) {
  604. if (testCounter == 0 || testCounter % 40)
  605. fprintf(stderr, "%*s", 40 - (testCounter % 40), "");
  606. fprintf(stderr, " %-3d %s\n", testCounter, ret == 0 ? "OK" : "FAIL");
  607. }
  608. return ret;
  609. }
  610. #ifdef HAVE_REGEX_H
  611. int virtTestClearLineRegex(const char *pattern,
  612. char *str)
  613. {
  614. regex_t reg;
  615. char *lineStart = str;
  616. char *lineEnd = strchr(str, '\n');
  617. if (regcomp(&reg, pattern, REG_EXTENDED | REG_NOSUB) != 0)
  618. return -1;
  619. while (lineStart) {
  620. int ret;
  621. if (lineEnd)
  622. *lineEnd = '\0';
  623. ret = regexec(&reg, lineStart, 0, NULL, 0);
  624. //fprintf(stderr, "Match %d '%s' '%s'\n", ret, lineStart, pattern);
  625. if (ret == 0) {
  626. if (lineEnd) {
  627. memmove(lineStart, lineEnd + 1, strlen(lineEnd+1) + 1);
  628. /* Don't update lineStart - just iterate again on this
  629. location */
  630. lineEnd = strchr(lineStart, '\n');
  631. } else {
  632. *lineStart = '\0';
  633. lineStart = NULL;
  634. }
  635. } else {
  636. if (lineEnd) {
  637. *lineEnd = '\n';
  638. lineStart = lineEnd + 1;
  639. lineEnd = strchr(lineStart, '\n');
  640. } else {
  641. lineStart = NULL;
  642. }
  643. }
  644. }
  645. regfree(&reg);
  646. return 0;
  647. }
  648. #else
  649. int virtTestClearLineRegex(const char *pattern ATTRIBUTE_UNUSED,
  650. char *str ATTRIBUTE_UNUSED)
  651. {
  652. return 0;
  653. }
  654. #endif