github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/tests.h (about)

     1  #include <string.h> // strlen()
     2  #include <math.h>   // signbit()
     3  #include <stdio.h>  // printf()
     4  #include <wchar.h>  // wcscmp()
     5  
     6  // When comparing floating-point numbers this is how many significant bits will
     7  // be used to calculate the epsilon.
     8  #define INT64 52 - 4
     9  #define INT32 23 - 4
    10  
    11  // approx() is used to compare floating-point numbers. It will automatically
    12  // calculate a very small epsilon (the difference between the two values that is
    13  // still considered equal) based on the expected value and number of bits.
    14  //
    15  // approx() is used by the is_eq() macro for comparing numbers of any kind
    16  // which makes it ideal for comparing different sized floats or other math that
    17  // might introduce rounding errors.
    18  #define approx(actual, expected) approxf(actual, expected, \
    19      sizeof(actual) != sizeof(expected) ? INT32 : INT64)
    20  
    21  // approxf() will strictly not handle any input value that is infinite or NaN.
    22  // It will always return false, even if the values are exactly equal. This is to
    23  // force you to use the correct matcher (ie. is_inf()) instead of relying on
    24  // comparisons which might not work.
    25  static int approxf(double actual, double expected, int bits) {
    26      // We do not handle infinities or NaN.
    27      if (isinf(actual) || isinf(expected) || isnan(actual) || isnan(expected)) {
    28          return 0;
    29      }
    30  
    31      // If we expect zero (a common case) we have a fixed epsilon from actual. If
    32      // allowed to continue the epsilon calculated would be zero and we would be
    33      // doing an exact match which is what we want to avoid.
    34      if (expected == 0.0) {
    35          return fabs(actual) < (1 / pow(2, bits));
    36      }
    37  
    38      // The epsilon is calculated based on significant bits of the actual value.
    39      // The amount of bits used depends on the original size of the float (in
    40      // terms of bits) subtracting a few to allow for very slight rounding
    41      // errors.
    42      double epsilon = fabs(expected / pow(2, bits));
    43  
    44      // The numbers are considered equal if the absolute difference between them
    45      // is less than the relative epsilon.
    46      return fabs(actual - expected) <= epsilon;
    47  }
    48  
    49  // isnegzero tests if a value is a negative zero. Negative zeros are a special
    50  // value of floating points that are equivalent in value, but not of bits to the
    51  // common 0.0 value.
    52  static int isnegzero(double x) {
    53      return (x * -0.0) == 0.0 && signbit(x);
    54  }
    55  
    56  // TAP: Below is a crude implementation of the TAP protocol for testing. If you
    57  // add any new functionality to this file that is not part of TAP you should
    58  // place that code above this comment.
    59  
    60  // The number for the current test. It is incremented before each check.
    61  static int current_test = 0;
    62  
    63  // The total number of tests expected to be run. This must be set with plan()
    64  // before any checks are performed.
    65  static int total_tests = 0;
    66  
    67  // The total number of failed tests.
    68  static int total_failures = 0;
    69  
    70  // Signals if the last test passed (1) or failed (0).
    71  static int last_test_was_ok = 1;
    72  
    73  // Set the number of expected tests/checks. This is important to prevent errors
    74  // that would cause the program to silently fail before the test suite is
    75  // finished.
    76  //
    77  // If the number of checks at the end (done_testing) is not the same as the
    78  // value provided here then the suite will fail.
    79  //
    80  // To avoid Gcc warning (unused-function),
    81  // force to call here the function isnegzero()
    82  #define plan(numberOfTests)      \
    83      isnegzero(1);                \
    84      total_tests = numberOfTests; \
    85      printf("1..%d\n", numberOfTests)
    86  
    87  // Print a diagnotic message or comment. Comments make the output more
    88  // understandable (such as headings or descriptions) and can be printed at any
    89  // time.
    90  //
    91  // diag() takes the same format and arguments as a printf().
    92  #define diag(...)        \
    93      printf("\n# ");      \
    94      printf(__VA_ARGS__); \
    95      printf("\n");
    96  
    97  // Check if the input is true. True in C is any value that is not a derivative
    98  // of zero (or NULL). Any other value, including negative values and fractions
    99  // are considered true.
   100  //
   101  // You should only use this when testing values that are integers or pointers.
   102  // Zero values in floating-points are not always reliable to compare exactly.
   103  #define is_true(actual)     \
   104      if (actual)             \
   105      {                       \
   106          pass("%s", #actual) \
   107      }                       \
   108      else                    \
   109      {                       \
   110          fail("%s", #actual) \
   111      }
   112  
   113  // Check if the input is false. This works in the exact opposite way as
   114  // is_true(). Be careful with floating-point values.
   115  #define is_false(actual)    \
   116      if (actual == 0)        \
   117      {                       \
   118          pass("%s", #actual) \
   119      }                       \
   120      else                    \
   121      {                       \
   122          fail("%s", #actual) \
   123      }
   124  
   125  // Immediately pass a check. This is useful if you are testing code flow, such
   126  // as reaching a particular if/else branch.
   127  //
   128  // pass() takes the same arguments as a printf().
   129  #define pass(...)                         \
   130      {                                     \
   131          ++current_test;                   \
   132          printf("%d ok - ", current_test); \
   133          printf(__VA_ARGS__);              \
   134          printf("\n");                     \
   135          last_test_was_ok = 1;             \
   136      }
   137  
   138  // Immediately fail a check. This is useful if you are testing code flow (such
   139  // as code that should not be reached or known bad conditions we met.
   140  //
   141  // fail() takes the same arguments as a printf().
   142  #define fail(...)                                                        \
   143      {                                                                    \
   144          ++current_test;                                                  \
   145          ++total_failures;                                                \
   146          printf("%d not ok - %s:%d: ", current_test, __FILE__, __LINE__); \
   147          printf(__VA_ARGS__);                                             \
   148          printf("\n");                                                    \
   149          last_test_was_ok = 0;                                            \
   150      }
   151  
   152  // Test if two values are equal. is_eq() will accept any *numerical* value than
   153  // can be cast to a double and compared. This does not work with strings, see
   154  // is_streq().
   155  //
   156  // Floating-point values are notoriously hard to compare exactly so the values
   157  // are compared through the approx() function also defined in this file.
   158  #define is_eq(actual, expected)                                            \
   159      if (approx((actual), (expected)))                                      \
   160      {                                                                      \
   161          pass("%s == %s", #actual, #expected)                               \
   162      }                                                                      \
   163      else                                                                   \
   164      {                                                                      \
   165          fail("%s == %s # got %.25g != %.25g. delta = %.25g",               \
   166                  #actual, #expected, (double)(actual), (double)(expected),  \
   167  				(double)(actual-expected))                                 \
   168      }
   169  
   170  // This works in the opposite way as is_eq().
   171  #define is_not_eq(actual, expected)                                     \
   172      if (approx((actual), (expected)))                                   \
   173      {                                                                   \
   174          fail("%s != %s # got %f", #actual, #expected, (double)(actual)) \
   175      }                                                                   \
   176      else                                                                \
   177      {                                                                   \
   178          pass("%s != %s", #actual, #expected)                            \
   179      }
   180  
   181  // Compare two C strings. The two strings are equal if they are the same length
   182  // (based on strlen) and each of their characters (actually bytes) are exactly
   183  // the same value. This is nor to be used with strings that are mixed case or
   184  // contain multibyte characters (eg. UTF-16, etc).
   185  #define is_streq(actual, expected)                                 \
   186      if (strcmp(actual, expected) == 0)                             \
   187      {                                                              \
   188          pass("%s == %s", #actual, #expected)                       \
   189      }                                                              \
   190      else                                                           \
   191      {                                                              \
   192          fail("%s (%d b) == %s (%d b) # got \"%s\"",                \
   193  		#actual, strlen(#actual),                                  \
   194          #expected, strlen(#expected),                              \
   195  		actual)                                                    \
   196      }
   197  
   198  // Compare two C wchars
   199  #define is_wchareq(actual, expected)                               \
   200      if (wcscmp(actual, expected) == 0)                             \
   201      {                                                              \
   202          pass("%s == %s", #actual, #expected)                       \
   203      }                                                              \
   204      else                                                           \
   205      {                                                              \
   206          fail("%s (%d b) == %s (%d b) # got \"%s\"", #actual,       \
   207              strlen(#actual), #expected, strlen(#expected), actual) \
   208      }
   209  
   210  // Check that a floating-point value is Not A Number. Passing a value that is
   211  // not floating point may lead to undefined behaviour.
   212  #define is_nan(actual)                              \
   213      if (isnan(actual))                              \
   214      {                                               \
   215          pass("isnan(%s)", #actual)                  \
   216      }                                               \
   217      else                                            \
   218      {                                               \
   219          fail("isnan(%s) # got %f", #actual, actual) \
   220      }
   221  
   222  // Check that a floating-point value is positive or negative infinity. A sign of
   223  // less than 0 will check for -inf and a sign greater than 0 will check for
   224  // +inf. A sign of 0 will always cause a failure.
   225  //
   226  // Mac and Linux check for infinity in different ways; either by using isinf()
   227  // or comparing directly with an INFINITY constant. We always use both methods.
   228  // This is separate checking the sign of the infinity.
   229  #define is_inf(actual, sign)                                                                    \
   230      {                                                                                           \
   231          int linuxInf = ((actual) == -INFINITY || (actual) == INFINITY);                         \
   232          int macInf = (isinf(actual) == 1);                                                      \
   233          if ((linuxInf || macInf) && ((sign > 0 && (actual) > 0) || (sign < 0 && (actual) < 0))) \
   234          {                                                                                       \
   235              pass("isinf(%s, %d)", #actual, sign)                                                \
   236          }                                                                                       \
   237          else                                                                                    \
   238          {                                                                                       \
   239              fail("isinf(%s, %d) # got %f", #actual, sign, actual)                               \
   240          }                                                                                       \
   241      }
   242  
   243  // Check that a value is a negative-zero. See isnegzero() for more information.
   244  // Using non-floating-point values with this may give unexpected results.
   245  #define is_negzero(actual) is_true(isnegzero(actual));
   246  
   247  #define is_null(actual)             \
   248      if (actual == NULL)             \
   249      {                               \
   250          pass("%s == NULL", #actual) \
   251      }                               \
   252      else                            \
   253      {                               \
   254          fail("%s == NULL", #actual) \
   255      }
   256  
   257  #define is_not_null(actual)         \
   258      if (actual != NULL)             \
   259      {                               \
   260          pass("%s != NULL", #actual) \
   261      }                               \
   262      else                            \
   263      {                               \
   264          fail("%s != NULL", #actual) \
   265      }
   266  
   267  // disabled will suppress checks. The check, and any code associated within it
   268  // will not be run at all. This is not the same as passing or skipping a test.
   269  #define disabled(x)
   270  
   271  // To signal that testing is now complete and to return the appropriate status
   272  // code. This should be the last line in the main() function.
   273  #define done_testing()                                                             \
   274      int exit_status = 0;                                                           \
   275      if (total_failures > 0)                                                        \
   276      {                                                                              \
   277          diag("FAILED: There was %d failed tests.", total_failures);                \
   278          exit_status = 101;                                                         \
   279      }                                                                              \
   280      if (current_test != total_tests)                                               \
   281      {                                                                              \
   282          diag("FAILED: Expected %d tests, but ran %d.", total_tests, current_test); \
   283          exit_status = 102;                                                         \
   284      }                                                                              \
   285      /* If we exit (with any status) the Go code coverage will not be generated. */ \
   286      if (exit_status != 0) {                                                        \
   287          return exit_status;                                                        \
   288      }                                                                              \
   289      return 0;
   290  
   291  // or_return will return (with an optional value provided) if the check failed.
   292  //
   293  //     is_not_null(filePointer) or_return();
   294  //
   295  #define or_return(...)      \
   296      if (!last_test_was_ok)  \
   297      {                       \
   298          return __VA_ARGS__; \
   299      }
   300  
   301  // Do not place code beyond this. See the TAP comment above.