1 /*
2 * librdkafka - Apache Kafka C library
3 *
4 * Copyright (c) 2012-2015, Magnus Edenhill
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 *    this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 *    this list of conditions and the following disclaimer in the documentation
14 *    and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28 #ifndef _TESTSHARED_H_
29 #define _TESTSHARED_H_
30 
31 /**
32  * C variables and functions shared with C++ tests
33  */
34 
35 typedef struct rd_kafka_s rd_kafka_t;
36 
37 /* ANSI color codes */
38 #define _C_CLR "\033[0m"
39 #define _C_RED "\033[31m"
40 #define _C_GRN "\033[32m"
41 #define _C_YEL "\033[33m"
42 #define _C_BLU "\033[34m"
43 #define _C_MAG "\033[35m"
44 #define _C_CYA "\033[36m"
45 
46 
47 /** Test scenario */
48 extern char test_scenario[64];
49 
50 /** @returns the \p msecs timeout multiplied by the test timeout multiplier */
51 extern int tmout_multip (int msecs);
52 
53 /** @brief true if tests should run in quick-mode (faster, less data) */
54 extern int test_quick;
55 
56 /** @brief Broker version to int */
57 #define TEST_BRKVER(A,B,C,D) \
58         (((A) << 24) | ((B) << 16) | ((C) << 8) | (D))
59 /** @brief return single version component from int */
60 #define TEST_BRKVER_X(V,I) \
61         (((V) >> (24-((I)*8))) & 0xff)
62 
63 /** @brief Topic Admin API supported by this broker version and later */
64 #define TEST_BRKVER_TOPIC_ADMINAPI TEST_BRKVER(0,10,2,0)
65 
66 extern int test_broker_version;
67 extern int test_on_ci;
68 
69 const char *test_mk_topic_name (const char *suffix, int randomized);
70 
71 void test_delete_topic (rd_kafka_t *use_rk, const char *topicname);
72 
73 void test_create_topic (rd_kafka_t *use_rk, const char *topicname,
74                         int partition_cnt, int replication_factor);
75 
76 uint64_t
77 test_produce_msgs_easy_size (const char *topic, uint64_t testid,
78                              int32_t partition, int msgcnt, size_t size);
79 #define test_produce_msgs_easy(topic,testid,partition,msgcnt) \
80         test_produce_msgs_easy_size(topic,testid,partition,msgcnt,0)
81 
82 
83 void test_fail0 (const char *file, int line, const char *function,
84                  int do_lock, int fail_now, const char *fmt, ...)
85         RD_FORMAT(printf, 6, 7);
86 
87 
88 
89 void test_fail0 (const char *file, int line, const char *function,
90                  int do_lock, int fail_now, const char *fmt, ...)
91         RD_FORMAT(printf, 6, 7);
92 
93 #define TEST_FAIL0(file,line,do_lock,fail_now,...)   \
94         test_fail0(__FILE__, __LINE__, __FUNCTION__, \
95                    do_lock, fail_now, __VA_ARGS__)
96 
97 /* Whine and abort test */
98 #define TEST_FAIL(...) TEST_FAIL0(__FILE__,__LINE__,1,1,__VA_ARGS__)
99 
100 /* Whine right away, mark the test as failed, but continue the test. */
101 #define TEST_FAIL_LATER(...) TEST_FAIL0(__FILE__,__LINE__,1,0,__VA_ARGS__)
102 
103 /* Whine right away, maybe mark the test as failed, but continue the test. */
104 #define TEST_FAIL_LATER0(LATER,...) TEST_FAIL0(__FILE__,__LINE__,1,!(LATER),__VA_ARGS__)
105 
106 #define TEST_FAILCNT()  (test_curr->failcnt)
107 
108 #define TEST_LATER_CHECK(...) do {                              \
109         if (test_curr->state == TEST_FAILED)                    \
110                 TEST_FAIL("See previous errors. " __VA_ARGS__); \
111         } while (0)
112 
113 #define TEST_PERROR(call) do {                                         \
114                if (!(call))                                            \
115                        TEST_FAIL(#call " failed: %s", rd_strerror(errno)); \
116        } while (0)
117 
118 #define TEST_WARN(...) do {                                              \
119                 fprintf(stderr, "\033[33m[%-28s/%7.3fs] WARN: ",       \
120                        test_curr->name,                                \
121                        test_curr->start ?                              \
122                        ((float)(test_clock() -                         \
123                                  test_curr->start)/1000000.0f) : 0);    \
124                fprintf(stderr, __VA_ARGS__);                           \
125                 fprintf(stderr, "\033[0m");                             \
126        } while (0)
127 
128 /* "..." is a failure reason in printf format, include as much info as needed */
129 #define TEST_ASSERT(expr,...) do {            \
130         if (!(expr)) {                        \
131                       TEST_FAIL("Test assertion failed: \"" # expr  "\": " \
132                                 __VA_ARGS__);                           \
133                       }                                                 \
134         } while (0)
135 
136 
137 /* "..." is a failure reason in printf format, include as much info as needed */
138 #define TEST_ASSERT_LATER(expr,...) do {                                \
139                 if (!(expr)) {                                          \
140                         TEST_FAIL0(__FILE__, __LINE__, 1, 0,            \
141                                    "Test assertion failed: \"" # expr  "\": " \
142                                    __VA_ARGS__);                        \
143                 }                                                       \
144         } while (0)
145 
146 
147 void test_SAY (const char *file, int line, int level, const char *str);
148 void test_SKIP (const char *file, int line, const char *str);
149 
150 void test_timeout_set (int timeout);
151 int test_set_special_conf (const char *name, const char *val, int *timeoutp);
152 const char *test_conf_get_path (void);
153 const char *test_getenv (const char *env, const char *def);
154 
155 int test_needs_auth (void);
156 
157 uint64_t test_id_generate (void);
158 char *test_str_id_generate (char *dest, size_t dest_size);
159 const char *test_str_id_generate_tmp (void);
160 
161 void test_prepare_msg (uint64_t testid, int32_t partition, int msg_id,
162                        char *val, size_t val_size,
163                        char *key, size_t key_size);
164 /**
165  * Parse a message token
166  */
167 void test_msg_parse00 (const char *func, int line,
168                        uint64_t testid, int32_t exp_partition, int *msgidp,
169                        const char *topic, int32_t partition, int64_t offset,
170                        const char *key, size_t key_size);
171 
172 
173 int test_check_builtin (const char *feature);
174 
175 /**
176  * @returns the current test's name (thread-local)
177  */
178 extern const char *test_curr_name (void);
179 
180 #ifndef _MSC_VER
181 #include <sys/time.h>
182 #ifndef RD_UNUSED
183 #define RD_UNUSED __attribute__((unused))
184 #endif
185 
186 #else
187 
188 #define WIN32_LEAN_AND_MEAN
189 #include <Windows.h>
190 #endif
191 
192 #ifndef RD_UNUSED
193 #define RD_UNUSED
194 #endif
195 
196 
197 /**
198 * A microsecond monotonic clock
199 */
200 static RD_INLINE int64_t test_clock (void)
201 #ifndef _MSC_VER
202 __attribute__((unused))
203 #endif
204 ;
test_clock(void)205 static RD_INLINE int64_t test_clock (void) {
206 #ifdef __APPLE__
207         /* No monotonic clock on Darwin */
208         struct timeval tv;
209         gettimeofday(&tv, NULL);
210         return ((int64_t)tv.tv_sec * 1000000LLU) + (int64_t)tv.tv_usec;
211 #elif _MSC_VER
212         LARGE_INTEGER now;
213         static RD_TLS LARGE_INTEGER freq;
214         if (!freq.QuadPart)
215                 QueryPerformanceFrequency(&freq);
216         QueryPerformanceCounter(&now);
217         return (now.QuadPart * 1000000) / freq.QuadPart;
218 #else
219         struct timespec ts;
220         clock_gettime(CLOCK_MONOTONIC, &ts);
221         return ((int64_t)ts.tv_sec * 1000000LLU) +
222                 ((int64_t)ts.tv_nsec / 1000LLU);
223 #endif
224 }
225 
226 
227 typedef struct test_timing_s {
228         char name[256];
229         int64_t ts_start;
230         int64_t duration;
231         int64_t ts_every; /* Last every */
232 } test_timing_t;
233 
234 /**
235  * @brief Start timing, Va-Argument is textual name (printf format)
236  */
237 #define TIMING_RESTART(TIMING) do {                                     \
238         (TIMING)->ts_start = test_clock();                              \
239         (TIMING)->duration = 0;                                         \
240         } while (0)
241 
242 #define TIMING_START(TIMING,...) do {                                   \
243         rd_snprintf((TIMING)->name, sizeof((TIMING)->name), __VA_ARGS__); \
244         TIMING_RESTART(TIMING);                                         \
245         (TIMING)->ts_every = (TIMING)->ts_start;                        \
246         } while (0)
247 
248 #define TIMING_STOPPED(TIMING) ((TIMING)->duration != 0)
249 
250 #ifndef __cplusplus
251 #define TIMING_STOP(TIMING) do {                                \
252         (TIMING)->duration = test_clock() - (TIMING)->ts_start; \
253         TEST_SAY("%s: duration %.3fms\n",                               \
254                  (TIMING)->name, (float)(TIMING)->duration / 1000.0f);  \
255         } while (0)
256 #define TIMING_REPORT(TIMING) \
257         TEST_SAY("%s: duration %.3fms\n",                               \
258                  (TIMING)->name, (float)(TIMING)->duration / 1000.0f);  \
259 
260 #else
261 #define TIMING_STOP(TIMING) do {                                        \
262         char _str[512];                                                 \
263         (TIMING)->duration = test_clock() - (TIMING)->ts_start;         \
264         rd_snprintf(_str, sizeof(_str), "%s: duration %.3fms\n",        \
265                     (TIMING)->name, (float)(TIMING)->duration / 1000.0f); \
266         Test::Say(_str);                                                \
267         } while (0)
268 
269 #endif
270 
271 #define TIMING_DURATION(TIMING) ((TIMING)->duration ? (TIMING)->duration : \
272                                  (test_clock() - (TIMING)->ts_start))
273 
274 #define TIMING_ASSERT0(TIMING,DO_FAIL_LATER,TMIN_MS,TMAX_MS) do {       \
275         if (!TIMING_STOPPED(TIMING))                                    \
276                 TIMING_STOP(TIMING);                                    \
277         int _dur_ms = (int)TIMING_DURATION(TIMING) / 1000;              \
278         if (TMIN_MS <= _dur_ms && _dur_ms <= TMAX_MS)                   \
279                 break;                                                  \
280         if (test_on_ci || strcmp(test_mode, "bare"))                    \
281                 TEST_WARN("%s: expected duration %d <= %d <= %d ms%s\n", \
282                           (TIMING)->name, TMIN_MS, _dur_ms, TMAX_MS,    \
283                           ": not FAILING test on CI");                  \
284         else                                                            \
285                 TEST_FAIL_LATER0(DO_FAIL_LATER,                         \
286                                  "%s: expected duration %d <= %d <= %d ms", \
287                                  (TIMING)->name, TMIN_MS, _dur_ms, TMAX_MS); \
288         } while (0)
289 
290 #define TIMING_ASSERT(TIMING,TMIN_MS,TMAX_MS)           \
291         TIMING_ASSERT0(TIMING,0,TMIN_MS,TMAX_MS)
292 #define TIMING_ASSERT_LATER(TIMING,TMIN_MS,TMAX_MS)     \
293         TIMING_ASSERT0(TIMING,1,TMIN_MS,TMAX_MS)
294 
295 /* Trigger something every US microseconds. */
TIMING_EVERY(test_timing_t * timing,int us)296 static RD_UNUSED int TIMING_EVERY (test_timing_t *timing, int us) {
297         int64_t now = test_clock();
298         if (timing->ts_every + us <= now) {
299                 timing->ts_every = now;
300                 return 1;
301         }
302         return 0;
303 }
304 
305 
306 #ifndef _MSC_VER
307 #define rd_sleep(S) sleep(S)
308 #else
309 #define rd_sleep(S) Sleep((S)*1000)
310 #endif
311 
312 /* Make sure __SANITIZE_ADDRESS__ (gcc) is defined if compiled with asan */
313 #if !defined(__SANITIZE_ADDRESS__) && defined(__has_feature)
314  #if __has_feature(address_sanitizer)
315  #define __SANITIZE_ADDRESS__ 1
316  #endif
317 #endif
318 
319 
320 int test_run_java (const char *cls, const char **argv);
321 int test_waitpid (int pid);
322 #endif /* _TESTSHARED_H_ */
323