Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
cunit: C++-ify s_xbt_test_test.
[simgrid.git] / src / xbt / cunit.cpp
index 94e16a66388483cfa556c0399b485372a59b58ab..70090dc90f1629542a454e7b7a48e852c8424abe 100644 (file)
@@ -1,7 +1,6 @@
 /* cunit - A little C Unit facility                                         */
 
-/* Copyright (c) 2005-2014. The SimGrid Team.
- * All rights reserved.                                                     */
+/* Copyright (c) 2005-2017. The SimGrid Team. All rights reserved.          */
 
 /* This program is free software; you can redistribute it and/or modify it
  * under the terms of the license (GNU LGPL) which comes with this package. */
 /* At some point we should use https://github.com/google/googletest instead */
 
 #include "src/internal_config.h"
-#include <stdio.h>
+#include <algorithm>
+#include <cstdio>
+#include <string>
+#include <vector>
 
+#include <xbt/cunit.h>
 #include <xbt/ex.hpp>
+#include <xbt/string.hpp>
+
 #include "xbt/sysdep.h"         /* bvprintf */
-#include "xbt/cunit.h"
 #include "xbt/dynar.h"
 
+#define STRLEN 1024
+
 /* collection of all suites */
 static xbt_dynar_t _xbt_test_suites = nullptr;
 /* global statistics */
@@ -39,42 +45,48 @@ static int _xbt_test_suite_disabled = 0;
 xbt_test_unit_t _xbt_test_current_unit = nullptr;
 
 /* test suite test log */
-typedef struct s_xbt_test_log {
-  char *text;
-  const char *file;
-  int line;
-} *xbt_test_log_t;
+class s_xbt_test_log {
+public:
+  s_xbt_test_log(std::string text, std::string file, int line)
+      : text_(std::move(text)), file_(std::move(file)), line_(line)
+  {
+  }
+  void dump() const;
+
+  std::string text_;
+  std::string file_;
+  int line_;
+};
 
-static void xbt_test_log_dump(xbt_test_log_t log)
+void s_xbt_test_log::dump() const
 {
-  if (log)
-    fprintf(stderr, "      log %p(%s:%d)=%s\n", log, log->file, log->line, log->text);
-  else
-    fprintf(stderr, "      log=nullptr\n");
+  fprintf(stderr, "      log %p(%s:%d)=%s\n", this, this->file_.c_str(), this->line_, this->text_.c_str());
 }
 
 /* test suite test check */
-typedef struct s_xbt_test_test {
-  char *title;
-  int failed;
-  int expected_failure;
-  int ignored;
-  const char *file;
-  int line;
-  xbt_dynar_t logs;
-} *xbt_test_test_t;
+class s_xbt_test_test {
+public:
+  s_xbt_test_test(std::string title, std::string file, int line)
+      : title_(std::move(title)), file_(std::move(file)), line_(line)
+  {
+  }
+  void dump() const;
+
+  std::string title_;
+  bool failed_           = false;
+  bool expected_failure_ = false;
+  bool ignored_          = false;
+  std::string file_;
+  int line_;
+  std::vector<s_xbt_test_log> logs_;
+};
 
-static void xbt_test_test_dump(xbt_test_test_t test)
+void s_xbt_test_test::dump() const
 {
-  if (test) {
-    xbt_test_log_t log;
-    unsigned int it_log;
-    fprintf(stderr, "    test %p(%s:%d)=%s (%s)\n", test, test->file, test->line, test->title,
-            test->failed ? "failed" : "not failed");
-    xbt_dynar_foreach(test->logs, it_log, log)
-        xbt_test_log_dump(log);
-  } else
-    fprintf(stderr, "    test=nullptr\n");
+  fprintf(stderr, "    test %p(%s:%d)=%s (%s)\n", this, this->file_.c_str(), this->line_, this->title_.c_str(),
+          this->failed_ ? "failed" : "not failed");
+  for (s_xbt_test_log const& log : this->logs_)
+    log.dump();
 }
 
 /* test suite test unit */
@@ -85,7 +97,7 @@ struct s_xbt_test_unit {
   ts_test_cb_t func;
   const char *file;
   int line;
-  xbt_dynar_t tests;            /* of xbt_test_test_t */
+  std::vector<s_xbt_test_test> tests;
 
   int nb_tests;
   int test_failed;
@@ -96,12 +108,11 @@ struct s_xbt_test_unit {
 static void xbt_test_unit_dump(xbt_test_unit_t unit)
 {
   if (unit) {
-    xbt_test_test_t test;
-    unsigned int it_test;
     fprintf(stderr, "  UNIT %s: %s (%s)\n", unit->name, unit->title, (unit->enabled ? "enabled" : "disabled"));
-    if (unit->enabled)
-      xbt_dynar_foreach(unit->tests, it_test, test)
-          xbt_test_test_dump(test);
+    if (unit->enabled) {
+      for (s_xbt_test_test const& test : unit->tests)
+        test.dump();
+    }
   } else {
     fprintf(stderr, "  unit=nullptr\n");
   }
@@ -140,40 +151,30 @@ static void xbt_test_unit_free(void *unit)
 {
   xbt_test_unit_t u = *(xbt_test_unit_t *) unit;
   /* name is static */
-  free(u->title);
-  xbt_dynar_free(&u->tests);
-  free(u);
+  xbt_free(u->title);
+  delete u;
 }
 
-static void xbt_test_test_free(void *test)
-{
-  xbt_test_test_t t = *(xbt_test_test_t *) test;
-  free(t->title);
-  xbt_dynar_free(&(t->logs));
-  free(t);
-}
-
-static void xbt_test_log_free(void *log)
-{
-  xbt_test_log_t l = *(xbt_test_log_t *) log;
-  free(l->text);
-  free(l);
-}
-
-/** @brief create test suite */
-xbt_test_suite_t xbt_test_suite_new(const char *name, const char *fmt, ...)
+/** @brief retrieve a testsuite from name, or create a new one */
+xbt_test_suite_t xbt_test_suite_by_name(const char *name, const char *fmt, ...)
 {
-  xbt_test_suite_t suite = xbt_new0(struct s_xbt_test_suite, 1);
-  va_list ap;
-
-  if (!_xbt_test_suites)
+  if (_xbt_test_suites == nullptr) {
     _xbt_test_suites = xbt_dynar_new(sizeof(xbt_test_suite_t), xbt_test_suite_free);
+  } else {
+    xbt_test_suite_t suite;
+    unsigned int it_suite;
+    xbt_dynar_foreach(_xbt_test_suites, it_suite, suite)
+      if (not strcmp(suite->name, name))
+        return suite;
+  }
 
+  xbt_test_suite_t suite = xbt_new0(s_xbt_test_suite, 1);
+  va_list ap;
   va_start(ap, fmt);
   suite->title = bvprintf(fmt, ap);
   suite->units = xbt_dynar_new(sizeof(xbt_test_unit_t), &xbt_test_unit_free);
   va_end(ap);
-  suite->name = name;
+  suite->name    = name;
   suite->enabled = 1;
 
   xbt_dynar_push(_xbt_test_suites, &suite);
@@ -181,40 +182,18 @@ xbt_test_suite_t xbt_test_suite_new(const char *name, const char *fmt, ...)
   return suite;
 }
 
-/** @brief retrieve a testsuite from name, or create a new one */
-xbt_test_suite_t xbt_test_suite_by_name(const char *name, const char *fmt, ...)
-{
-  xbt_test_suite_t suite;
-  unsigned int it_suite;
-
-  char *bufname;
-  va_list ap;
-
-  if (_xbt_test_suites)
-    xbt_dynar_foreach(_xbt_test_suites, it_suite, suite)
-        if (!strcmp(suite->name, name))
-      return suite;
-
-  va_start(ap, fmt);
-  bufname = bvprintf(fmt, ap);
-  va_end(ap);
-  suite = xbt_test_suite_new(name, bufname, nullptr);
-  free(bufname);
-
-  return suite;
-}
-
-void xbt_test_suite_dump(xbt_test_suite_t suite)
+static void xbt_test_suite_dump(xbt_test_suite_t suite)
 {
   if (suite) {
-    xbt_test_unit_t unit;
-    unsigned int it_unit;
     fprintf(stderr, "TESTSUITE %s: %s (%s)\n", suite->name, suite->title, suite->enabled ? "enabled" : "disabled");
-    if (suite->enabled)
+    if (suite->enabled) {
+      xbt_test_unit_t unit;
+      unsigned int it_unit;
       xbt_dynar_foreach(suite->units, it_unit, unit)
           xbt_test_unit_dump(unit);
+    }
   } else {
-    fprintf(stderr, "TESTSUITE IS nullptr!\n");
+    fprintf(stderr, "TESTSUITE IS NULL!\n");
   }
 }
 
@@ -228,7 +207,7 @@ void xbt_test_suite_push(xbt_test_suite_t suite, const char *name, ts_test_cb_t
   xbt_assert(func);
   xbt_assert(fmt);
 
-  unit = xbt_new0(struct s_xbt_test_unit, 1);
+  unit = xbt_new0(s_xbt_test_unit, 1);
   va_start(ap, fmt);
   unit->title = bvprintf(fmt, ap);
   va_end(ap);
@@ -237,7 +216,6 @@ void xbt_test_suite_push(xbt_test_suite_t suite, const char *name, ts_test_cb_t
   unit->file = nullptr;
   unit->line = 0;
   unit->enabled = 1;
-  unit->tests = xbt_dynar_new(sizeof(xbt_test_test_t), xbt_test_test_free);
 
   xbt_dynar_push(suite->units, &unit);
 }
@@ -246,17 +224,6 @@ void xbt_test_suite_push(xbt_test_suite_t suite, const char *name, ts_test_cb_t
 static int xbt_test_suite_run(xbt_test_suite_t suite, int verbosity)
 {
   xbt_test_unit_t unit;
-  xbt_test_test_t test;
-  xbt_test_log_t log;
-
-  const char *file;
-  int line;
-  char *cp;
-  unsigned int it_unit;
-  unsigned int it_test;
-  unsigned int it_log;
-
-  int first = 1;                /* for result pretty printing */
 
   if (suite == nullptr)
     return 0;
@@ -275,12 +242,13 @@ static int xbt_test_suite_run(xbt_test_suite_t suite, int verbosity)
 
   snprintf(suite_title + 40 - (suite_len + 4) / 2, 81 - (40 - (suite_len + 4) / 2), "[ %s ]", suite->title);
   suite_title[40 + (suite_len + 5) / 2] = '=';
-  if (!suite->enabled)
+  if (not suite->enabled)
     snprintf(suite_title + 70, 11, " DISABLED ");
   fprintf(stderr, "\n%s\n", suite_title);
 
   if (suite->enabled) {
     /* iterate through all tests */
+    unsigned int it_unit;
     xbt_dynar_foreach(suite->units, it_unit, unit) {
       /* init unit case counters */
       unit->nb_tests = 0;
@@ -289,8 +257,9 @@ static int xbt_test_suite_run(xbt_test_suite_t suite, int verbosity)
       unit->test_expect = 0;
 
       /* display unit title */
-      cp = bprintf(" Unit: %s ......................................"
-                   "......................................", unit->title);
+      char* cp = bprintf(" Unit: %s ......................................"
+                         "......................................",
+                         unit->title);
       cp[70] = '\0';
       fprintf(stderr, "%s", cp);
       free(cp);
@@ -301,17 +270,15 @@ static int xbt_test_suite_run(xbt_test_suite_t suite, int verbosity)
         unit->func();
 
       /* iterate through all performed tests to determine status */
-      xbt_dynar_foreach(unit->tests, it_test, test) {
-        if (test->ignored) {
+      for (s_xbt_test_test const& test : unit->tests) {
+        if (test.ignored_) {
           unit->test_ignore++;
         } else {
           unit->nb_tests++;
 
-          if (test->failed && !test->expected_failure)
+          if ((test.failed_ && not test.expected_failure_) || (not test.failed_ && test.expected_failure_))
             unit->test_failed++;
-          if (!test->failed && test->expected_failure)
-            unit->test_failed++;
-          if (test->expected_failure)
+          if (test.expected_failure_)
             unit->test_expect++;
         }
       }
@@ -325,30 +292,30 @@ static int xbt_test_suite_run(xbt_test_suite_t suite, int verbosity)
         } else {
           fprintf(stderr, ".... skip\n");       /* shouldn't happen, but I'm a bit lost with this logic */
         }
-        xbt_dynar_foreach(unit->tests, it_test, test) {
-          file = (test->file != nullptr ? test->file : unit->file);
-          line = (test->line != 0 ? test->line : unit->line);
+        for (s_xbt_test_test const& test : unit->tests) {
+          std::string file = (test.file_.empty() ? unit->file : test.file_);
+          int line         = (test.line_ == 0 ? unit->line : test.line_);
           const char* resname;
-          if (test->ignored)
+          if (test.ignored_)
             resname = " SKIP";
-          else if (test->expected_failure) {
-            if (test->failed)
+          else if (test.expected_failure_) {
+            if (test.failed_)
               resname = "EFAIL";
             else
               resname = "EPASS";
           } else {
-            if (test->failed)
+            if (test.failed_)
               resname = " FAIL";
             else
               resname = " PASS";
           }
-          fprintf(stderr, "      %s: %s [%s:%d]\n", resname, test->title, file, line);
+          fprintf(stderr, "      %s: %s [%s:%d]\n", resname, test.title_.c_str(), file.c_str(), line);
 
-          if ((test->expected_failure && !test->failed) || (!test->expected_failure && test->failed)) {
-            xbt_dynar_foreach(test->logs, it_log, log) {
-              file = (log->file != nullptr ? log->file : file);
-              line = (log->line != 0 ? log->line : line);
-              fprintf(stderr, "             %s:%d: %s\n", file, line, log->text);
+          if ((test.expected_failure_ && not test.failed_) || (not test.expected_failure_ && test.failed_)) {
+            for (s_xbt_test_log const& log : test.logs_) {
+              file = (log.file_.empty() ? file : log.file_);
+              line = (log.line_ == 0 ? line : log.line_);
+              fprintf(stderr, "             %s:%d: %s\n", file.c_str(), line, log.text_.c_str());
             }
           }
         }
@@ -358,7 +325,7 @@ static int xbt_test_suite_run(xbt_test_suite_t suite, int verbosity)
         } else {
           fprintf(stderr, "\n");
         }
-      } else if (!unit->enabled) {
+      } else if (not unit->enabled) {
         fprintf(stderr, " disabled\n"); /* no test were run */
       } else if (unit->nb_tests) {
         fprintf(stderr, "...... ok\n"); /* successful */
@@ -382,7 +349,7 @@ static int xbt_test_suite_run(xbt_test_suite_t suite, int verbosity)
         suite->nb_units++;
         if (unit->test_failed)
           suite->unit_failed++;
-      } else if (!unit->enabled) {
+      } else if (not unit->enabled) {
         suite->unit_disabled++;
       } else {
         suite->unit_ignore++;
@@ -398,7 +365,7 @@ static int xbt_test_suite_run(xbt_test_suite_t suite, int verbosity)
     _xbt_test_nb_suites++;
     if (suite->test_failed)
       _xbt_test_suite_failed++;
-  } else if (!suite->enabled) {
+  } else if (not suite->enabled) {
     _xbt_test_suite_disabled++;
   } else {
     _xbt_test_suite_ignore++;
@@ -406,6 +373,8 @@ static int xbt_test_suite_run(xbt_test_suite_t suite, int verbosity)
 
   /* print test suite summary */
   if (suite->enabled) {
+    int first = 1; /* for result pretty printing */
+
     fprintf(stderr," =====================================================================%s\n",
             (suite->nb_units ? (suite->unit_failed ? "== FAILED" : "====== OK") :
                                (suite->unit_disabled ? " DISABLED" : "==== SKIP")));
@@ -456,32 +425,29 @@ static void apply_selection(char *selection)
   /* for the parsing */
   char *sel = selection;
   int done = 0;
-  char dir[1024];               /* the directive */
+  char dir[STRLEN]; /* the directive */
   /* iterators */
   unsigned int it_suite;
   xbt_test_suite_t suite;
   xbt_test_unit_t unit;
   unsigned int it_unit;
 
-  char suitename[512];
-  char unitname[512];
+  char suitename[STRLEN];
+  char unitname[STRLEN];
 
-  if (!selection || selection[0] == '\0')
+  if (not selection || selection[0] == '\0')
     return;
 
-  /*printf("Test selection: %s\n", selection); */
-
   /* First apply the selection */
-  while (!done) {
+  while (not done) {
     int enabling = 1;
 
     char *p = strchr(sel, ',');
     if (p) {
-      strncpy(dir, sel, p - sel);
-      dir[p - sel] = '\0';
+      snprintf(dir, STRLEN, "%.*s", (int)(p - sel), sel);
       sel = p + 1;
     } else {
-      strncpy(dir, sel,1024);
+      snprintf(dir, STRLEN, "%s", sel);
       done = 1;
     }
 
@@ -496,16 +462,15 @@ static void apply_selection(char *selection)
 
     p = strchr(dir, ':');
     if (p) {
-      strncpy(unitname, p + 1,512);
-      strncpy(suitename, dir, p - dir);
-      suitename[p - dir] = '\0';
+      snprintf(suitename, STRLEN, "%.*s", (int)(p - dir), dir);
+      snprintf(unitname, STRLEN, "%s", p + 1);
     } else {
-      strncpy(suitename, dir,512);
+      snprintf(suitename, STRLEN, "%s", dir);
       unitname[0] = '\0';
     }
 
     /* Deal with the specific case of 'all' pseudo serie */
-    if (!strcmp("all", suitename)) {
+    if (not strcmp("all", suitename)) {
       xbt_assert(unitname[0] == '\0', "The 'all' pseudo-suite does not accept any unit specification\n");
 
       xbt_dynar_foreach(_xbt_test_suites, it_suite, suite) {
@@ -519,7 +484,7 @@ static void apply_selection(char *selection)
       for (it = 0; it < xbt_dynar_length(_xbt_test_suites); it++) {
         xbt_test_suite_t thissuite =
             xbt_dynar_get_as(_xbt_test_suites, it, xbt_test_suite_t);
-        if (!strcmp(suitename, thissuite->name)) {
+        if (not strcmp(suitename, thissuite->name)) {
           /* Do not disable the whole suite when we just want to disable a child */
           if (enabling || (unitname[0] == '\0'))
             thissuite->enabled = enabling;
@@ -535,7 +500,7 @@ static void apply_selection(char *selection)
                  it2_unit < xbt_dynar_length(thissuite->units);
                  it2_unit++) {
               xbt_test_unit_t thisunit = xbt_dynar_get_as(thissuite->units, it2_unit, xbt_test_unit_t);
-              if (!strcmp(thisunit->name, unitname)) {
+              if (not strcmp(thisunit->name, unitname)) {
                 thisunit->enabled = enabling;
                 break;
               }
@@ -650,17 +615,9 @@ void _xbt_test_add(const char *file, int line, const char *fmt, ...)
   xbt_assert(unit);
 
   va_list ap;
-  xbt_test_test_t test = xbt_new0(struct s_xbt_test_test, 1);
   va_start(ap, fmt);
-  test->title = bvprintf(fmt, ap);
+  unit->tests.emplace_back(simgrid::xbt::string_vprintf(fmt, ap), file, line);
   va_end(ap);
-  test->failed = 0;
-  test->expected_failure = 0;
-  test->ignored = 0;
-  test->file = file;
-  test->line = line;
-  test->logs = xbt_dynar_new(sizeof(xbt_test_log_t), xbt_test_log_free);
-  xbt_dynar_push(unit->tests, &test);
 }
 
 /* annotate test case with log message and failure */
@@ -668,21 +625,16 @@ void _xbt_test_fail(const char *file, int line, const char *fmt, ...)
 {
   xbt_test_unit_t unit = _xbt_test_current_unit;
   xbt_assert(unit);
-  xbt_assert(xbt_dynar_length(_xbt_test_current_unit->tests),
-      "Test failed even before being declared (broken unit: %s)", unit->title);
+  xbt_assert(not _xbt_test_current_unit->tests.empty(), "Test failed even before being declared (broken unit: %s)",
+             unit->title);
 
+  s_xbt_test_test& test = unit->tests.back();
   va_list ap;
-  xbt_test_log_t log = xbt_new(struct s_xbt_test_log, 1);
   va_start(ap, fmt);
-  log->text = bvprintf(fmt, ap);
+  test.logs_.emplace_back(simgrid::xbt::string_vprintf(fmt, ap), file, line);
   va_end(ap);
-  log->file = file;
-  log->line = line;
-
-  xbt_test_test_t test = xbt_dynar_getlast_as(unit->tests, xbt_test_test_t);
-  xbt_dynar_push(test->logs, &log);
 
-  test->failed = 1;
+  test.failed_ = true;
 }
 
 void xbt_test_exception(xbt_ex_t e)
@@ -692,18 +644,17 @@ void xbt_test_exception(xbt_ex_t e)
 
 void xbt_test_expect_failure()
 {
-  xbt_assert(xbt_dynar_length(_xbt_test_current_unit->tests),
-      "Cannot expect the failure of a test before declaring it (broken unit: %s)", _xbt_test_current_unit->title);
-  xbt_test_test_t test = xbt_dynar_getlast_as(_xbt_test_current_unit->tests, xbt_test_test_t);
-  test->expected_failure = 1;
+  xbt_assert(not _xbt_test_current_unit->tests.empty(),
+             "Cannot expect the failure of a test before declaring it (broken unit: %s)",
+             _xbt_test_current_unit->title);
+  _xbt_test_current_unit->tests.back().expected_failure_ = true;
 }
 
 void xbt_test_skip()
 {
-  xbt_assert(xbt_dynar_length(_xbt_test_current_unit->tests),
-      "Test skipped even before being declared (broken unit: %s)", _xbt_test_current_unit->title);
-  xbt_test_test_t test = xbt_dynar_getlast_as(_xbt_test_current_unit->tests, xbt_test_test_t);
-  test->ignored = 1;
+  xbt_assert(not _xbt_test_current_unit->tests.empty(), "Test skipped even before being declared (broken unit: %s)",
+             _xbt_test_current_unit->title);
+  _xbt_test_current_unit->tests.back().ignored_ = true;
 }
 
 /* annotate test case with log message only */
@@ -711,19 +662,13 @@ void _xbt_test_log(const char *file, int line, const char *fmt, ...)
 {
   xbt_test_unit_t unit = _xbt_test_current_unit;
   xbt_assert(unit);
-  xbt_assert(xbt_dynar_length(_xbt_test_current_unit->tests),
-      "Test logged into even before being declared (broken test unit: %s)", unit->title);
+  xbt_assert(not _xbt_test_current_unit->tests.empty(),
+             "Test logged into even before being declared (broken test unit: %s)", unit->title);
 
   va_list ap;
-  xbt_test_log_t log = xbt_new(struct s_xbt_test_log, 1);
   va_start(ap, fmt);
-  log->text = bvprintf(fmt, ap);
+  unit->tests.back().logs_.emplace_back(simgrid::xbt::string_vprintf(fmt, ap), file, line);
   va_end(ap);
-  log->file = file;
-  log->line = line;
-
-  xbt_test_test_t test = xbt_dynar_getlast_as(unit->tests, xbt_test_test_t);
-  xbt_dynar_push(test->logs, &log);
 }
 
 #ifdef SIMGRID_TEST