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.