test_util.h 10.4 KB
Newer Older
1
/*
2
 * Copyright (c) 2014-2018 Cesanta Software Limited
3 4
 * All rights reserved
 *
5 6 7
 * Licensed under the Apache License, Version 2.0 (the ""License"");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
8
 *
9 10 11 12 13 14 15
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an ""AS IS"" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
16 17 18 19 20 21 22 23 24 25 26 27 28 29
 */

#ifndef CS_COMMON_TEST_UTIL_H_
#define CS_COMMON_TEST_UTIL_H_

#include <string.h>
#include <stdio.h>

#include "common/cs_time.h"

#ifdef __cplusplus
extern "C" {
#endif

30
extern int g_num_tests;
31
extern int g_num_checks;
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51

#ifdef MG_TEST_ABORT_ON_FAIL
#define MG_TEST_ABORT abort()
#else
#define MG_TEST_ABORT
#endif

int _assert_streq(const char *actual, const char *expected);
int _assert_streq_nz(const char *actual, const char *expected);
void _strfail(const char *a, const char *e, int len);

#define FAIL(str, line)                                              \
  do {                                                               \
    printf("%s:%d:1 [%s] (in %s)\n", __FILE__, line, str, __func__); \
    MG_TEST_ABORT;                                                   \
    return str;                                                      \
  } while (0)

#define ASSERT(expr)                    \
  do {                                  \
52
    g_num_checks++;                     \
53 54
    if (!(expr)) FAIL(#expr, __LINE__); \
  } while (0)
55 56
#define ASSERT_TRUE(expr) ASSERT(expr)
#define ASSERT_FALSE(expr) ASSERT(!(expr))
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74

/*
 * Run test function, use its name as the test name to print
 */
#define RUN_TEST(test) RUN_TEST_WNAME(test, #test)

/*
 * Run test function, use the provided name as the test name to print
 */
#define RUN_TEST_WNAME(test, test_name)            \
  do {                                             \
    const char *msg = NULL;                        \
    if (strstr(test_name, filter)) {               \
      double elapsed = cs_time();                  \
      msg = test();                                \
      elapsed = cs_time() - elapsed;               \
      printf("  [%.3f] %s\n", elapsed, test_name); \
      fflush(stdout);                              \
75
      g_num_tests++;                               \
76 77 78 79
    }                                              \
    if (msg) return msg;                           \
  } while (0)

80
/* VC6 doesn't have long long. */
81
#if (defined(_MSC_VER) && _MSC_VER <= 1200)
82
#define LONG_TYPE int64_t
83
#else
84
#define LONG_TYPE long long
85
#endif
86 87 88
#define AS_DOUBLE(d) (double)(d)

#define RANGE_CHECK(x) (fabs(x) > 4503599627370496.0 /* 2 << 51 */)
89 90

/*
91 92 93
 * Numeric equality assertion.
 * Args are cast to double to ensure aruemnts are only evaluated once.
 * This will work fine for all integer types except large 64-bit values.
94
 */
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
#define ASSERT_EQ(actual, expected)                         \
  do {                                                      \
    const double ad = AS_DOUBLE(actual);                    \
    const double ed = AS_DOUBLE(expected);                  \
    if (RANGE_CHECK(ad) || RANGE_CHECK(ed)) {               \
      FAIL("loss of precision, use ASSERT_EQ64", __LINE__); \
    }                                                       \
    g_num_checks++;                                         \
    if (!(ad == ed)) {                                      \
      printf("%lf != %lf\n", ad, ed);                       \
      FAIL(#actual " != " #expected, __LINE__);             \
    }                                                       \
  } while (0)

#define ASSERT_EQ64(actual, expected)            \
  do {                                           \
    const LONG_TYPE a64 = (LONG_TYPE)(actual);   \
    const LONG_TYPE e64 = (LONG_TYPE)(expected); \
    g_num_checks++;                              \
    if (!(a64 == e64)) {                         \
      printf("%lld != %lld\n", a64, e64);        \
      FAIL(#actual " != " #expected, __LINE__);  \
    }                                            \
  } while (0)

#define ASSERT_NE(actual, expected)                         \
  do {                                                      \
    const double ad = AS_DOUBLE(actual);                    \
    const double ed = AS_DOUBLE(expected);                  \
    g_num_checks++;                                         \
    if (RANGE_CHECK(ad) || RANGE_CHECK(ed)) {               \
      FAIL("loss of precision, use ASSERT_NE64", __LINE__); \
    }                                                       \
    if (!(ad != ed)) {                                      \
      printf("%lf == %lf\n", ad, ed);                       \
      FAIL(#actual " == " #expected, __LINE__);             \
    }                                                       \
  } while (0)

#define ASSERT_NE64(actual, expected)            \
  do {                                           \
    const LONG_TYPE a64 = (LONG_TYPE)(actual);   \
    const LONG_TYPE e64 = (LONG_TYPE)(expected); \
    g_num_checks++;                              \
    if (!(a64 != e64)) {                         \
      printf("%lld == %lld\n", a64, e64);        \
      FAIL(#actual " == " #expected, __LINE__);  \
    }                                            \
143 144 145
  } while (0)

/* "Less than" assertion. */
146 147 148 149 150 151 152 153 154 155 156 157
#define ASSERT_LT(a, b)                                  \
  do {                                                   \
    const double ad = AS_DOUBLE(a);                      \
    const double bd = AS_DOUBLE(b);                      \
    g_num_checks++;                                      \
    if (RANGE_CHECK(ad) || RANGE_CHECK(bd)) {            \
      FAIL("loss of precision in comparison", __LINE__); \
    }                                                    \
    if (!(ad < bd)) {                                    \
      printf("%lf >= %lf\n", ad, bd);                    \
      FAIL(#a " < " #b, __LINE__);                       \
    }                                                    \
158 159 160
  } while (0)

/* "Greater than" assertion. */
161 162 163 164 165 166 167 168 169
#define ASSERT_GT(a, b)               \
  do {                                \
    const double ad = AS_DOUBLE(a);   \
    const double bd = AS_DOUBLE(b);   \
    g_num_checks++;                   \
    if (!(ad > bd)) {                 \
      printf("%lf <= %lf\n", ad, bd); \
      FAIL(#a " > " #b, __LINE__);    \
    }                                 \
170 171 172 173 174
  } while (0)

/* Assert that actual == expected, where both are NUL-terminated. */
#define ASSERT_STREQ(actual, expected)                            \
  do {                                                            \
175
    g_num_checks++;                                               \
176
    if (!_assert_streq((actual), (expected))) {                   \
177 178 179 180 181 182 183
      FAIL("ASSERT_STREQ(" #actual ", " #expected ")", __LINE__); \
    }                                                             \
  } while (0)

/* Assert that actual == expected, where both are pointers */
#define ASSERT_PTREQ(actual, expected)                            \
  do {                                                            \
184 185
    const void *ap = (const void *) (actual);                     \
    const void *ep = (const void *) (expected);                   \
186
    g_num_checks++;                                               \
187 188
    if (!(ap == ep)) {                                            \
      printf("%p != %p\n", ap, ep);                               \
189 190 191 192 193
      FAIL("ASSERT_PTREQ(" #actual ", " #expected ")", __LINE__); \
    }                                                             \
  } while (0)

/* Assert that actual != expected, where both are pointers */
194 195 196 197 198 199 200 201 202
#define ASSERT_PTRNE(actual, expected)                            \
  do {                                                            \
    const void *ap = (const void *) (actual);                     \
    const void *ep = (const void *) (expected);                   \
    g_num_checks++;                                               \
    if (!(ap != ep)) {                                            \
      printf("%p == %p\n", ap, ep);                               \
      FAIL("ASSERT_PTRNE(" #actual ", " #expected ")", __LINE__); \
    }                                                             \
203 204 205 206 207
  } while (0)

/* Same as STREQ, but only expected is NUL-terminated. */
#define ASSERT_STREQ_NZ(actual, expected)                            \
  do {                                                               \
208
    g_num_checks++;                                                  \
209 210 211 212 213 214 215
    if (!_assert_streq_nz(actual, expected)) {                       \
      FAIL("ASSERT_STREQ_NZ(" #actual ", " #expected ")", __LINE__); \
    }                                                                \
  } while (0)

#define ASSERT_MG_STREQ(actual, expected)                            \
  do {                                                               \
216
    g_num_checks++;                                                  \
217 218 219 220 221 222 223 224
    if ((actual).len != strlen(expected) ||                          \
        memcmp((actual).p, expected, (actual).len) != 0) {           \
      printf("'%.*s' (%d) != '%s'\n", (int)(actual).len, (actual).p, \
             (int)(actual).len, expected);                           \
      FAIL("ASSERT_MG_STREQ(" #actual ", " #expected ")", __LINE__); \
    }                                                                \
  } while (0)

225 226 227 228 229 230 231
#define CHECK_CALL(call)                                                  \
  do {                                                                    \
    const char *r = (call);                                               \
    if (r != NULL) {                                                      \
      fprintf(stderr, "... %s:%d in %s\n", __FILE__, __LINE__, __func__); \
      return r;                                                           \
    }                                                                     \
232 233
  } while (0)

234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
#ifndef MG_ENABLE_POLL_UNTIL
#define MG_ENABLE_POLL_UNTIL 0
#endif

#if MG_ENABLE_POLL_UNTIL
#include "mongoose.h"
int c_str_ne(void *a, void *b);
int c_int_ne(void *a, void *b);
int c_int_eq(void *a, void *b);
void poll_until(struct mg_mgr *mgr, double timeout, int (*cond)(void *, void *),
                void *cond_arg1, void *cond_arg2);
#endif

#ifdef __cplusplus
}
#endif

#endif /* CS_COMMON_TEST_UTIL_H_ */