1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 #ifndef TEST_COMMON_H
18 #define TEST_COMMON_H
19
20 #include <src/include/pmix_config.h>
21 #include <pmix_common.h>
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <stdint.h>
28
29 #include "src/include/pmix_globals.h"
30 #include "src/class/pmix_list.h"
31 #include "src/util/argv.h"
32
33 #define TEST_NAMESPACE "smoky_nspace"
34 #define TEST_CREDENTIAL "dummy"
35
36 #define PMIX_WAIT_FOR_COMPLETION(m) \
37 do { \
38 while ((m)) { \
39 usleep(10); \
40 } \
41 } while(0)
42
43
44
45
46
47 char *pmix_test_output_prepare(const char *fmt,... );
48 extern int pmix_test_verbose;
49 extern FILE *file;
50
51 #define STRIPPED_FILE_NAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
52
53 #define TEST_OUTPUT(x) { \
54 fprintf(file,"==%d== %s:%s: %s\n", getpid(), STRIPPED_FILE_NAME, __func__, \
55 pmix_test_output_prepare x ); \
56 fflush(file); \
57 }
58
59
60
61 #define TEST_OUTPUT_CLEAR(x) { \
62 fprintf(file, "==%d== %s", getpid(), pmix_test_output_prepare x ); \
63 fflush(file); \
64 }
65
66
67 #define TEST_ERROR(x) { \
68 fprintf(stderr,"==%d== ERROR [%s:%d:%s]: %s\n", getpid(), STRIPPED_FILE_NAME, __LINE__, __func__, \
69 pmix_test_output_prepare x ); \
70 fflush(stderr); \
71 }
72
73 #define TEST_VERBOSE_ON() (pmix_test_verbose = 1)
74 #define TEST_VERBOSE_GET() (pmix_test_verbose)
75
76 #define TEST_VERBOSE(x) { \
77 if( pmix_test_verbose ){ \
78 TEST_OUTPUT(x); \
79 } \
80 }
81
82 #define TEST_DEFAULT_TIMEOUT 10
83 #define MAX_DIGIT_LEN 10
84 #define TEST_REPLACE_DEFAULT "3:1"
85
86 #define TEST_SET_FILE(prefix, ns_id, rank) { \
87 char *fname = malloc( strlen(prefix) + MAX_DIGIT_LEN + 2 ); \
88 sprintf(fname, "%s.%d.%d", prefix, ns_id, rank); \
89 file = fopen(fname, "w"); \
90 free(fname); \
91 if( NULL == file ){ \
92 fprintf(stderr, "Cannot open file %s for writing!", fname); \
93 exit(1); \
94 } \
95 }
96
97 #define TEST_CLOSE_FILE() { \
98 if ( stderr != file ) { \
99 fclose(file); \
100 } \
101 }
102
103 typedef struct {
104 char *binary;
105 char *np;
106 char *prefix;
107 char *nspace;
108 uint32_t nprocs;
109 int timeout;
110 int verbose;
111 pmix_rank_t rank;
112 int early_fail;
113 int test_job_fence;
114 int collect_bad;
115 int use_same_keys;
116 int collect;
117 int nonblocking;
118 char *fences;
119 char *noise;
120 char *ns_dist;
121 int ns_size;
122 int ns_id;
123 pmix_rank_t base_rank;
124 int test_publish;
125 int test_spawn;
126 int test_connect;
127 int test_resolve_peers;
128 int test_error;
129 char *key_replace;
130 int test_internal;
131 char *gds_mode;
132 int nservers;
133 uint32_t lsize;
134 } test_params;
135
136 #define INIT_TEST_PARAMS(params) do { \
137 params.nprocs = 1; \
138 params.verbose = 0; \
139 params.rank = PMIX_RANK_UNDEF; \
140 params.base_rank = 0; \
141 params.early_fail = 0; \
142 params.ns_size = -1; \
143 params.ns_id = -1; \
144 params.timeout = TEST_DEFAULT_TIMEOUT; \
145 params.test_job_fence = 0; \
146 params.use_same_keys = 0; \
147 params.collect = 0; \
148 params.collect_bad = 0; \
149 params.nonblocking = 0; \
150 params.test_publish = 0; \
151 params.test_spawn = 0; \
152 params.test_connect = 0; \
153 params.test_resolve_peers = 0; \
154 params.binary = NULL; \
155 params.np = NULL; \
156 params.prefix = NULL; \
157 params.nspace = NULL; \
158 params.fences = NULL; \
159 params.noise = NULL; \
160 params.ns_dist = NULL; \
161 params.test_error = 0; \
162 params.key_replace = NULL; \
163 params.test_internal = 0; \
164 params.gds_mode = NULL; \
165 params.nservers = 1; \
166 params.lsize = 0; \
167 } while (0)
168
169 #define FREE_TEST_PARAMS(params) do { \
170 if (NULL != params.binary) { \
171 free(params.binary); \
172 } \
173 if (NULL != params.np) { \
174 free(params.np); \
175 } \
176 if (NULL != params.prefix) { \
177 free(params.prefix); \
178 } \
179 if (NULL != params.nspace) { \
180 free(params.nspace); \
181 } \
182 if (NULL != params.fences) { \
183 free(params.fences); \
184 } \
185 if (NULL != params.noise) { \
186 free(params.noise); \
187 } \
188 if (NULL != params.ns_dist) { \
189 free(params.ns_dist); \
190 } \
191 } while (0)
192
193 void parse_cmd(int argc, char **argv, test_params *params);
194 int parse_fence(char *fence_param, int store);
195 int parse_noise(char *noise_param, int store);
196 int parse_replace(char *replace_param, int store, int *key_num);
197
198 typedef struct {
199 pmix_list_item_t super;
200 int blocking;
201 int data_exchange;
202 pmix_list_t *participants;
203 } fence_desc_t;
204 PMIX_CLASS_DECLARATION(fence_desc_t);
205
206 typedef struct {
207 pmix_list_item_t super;
208 pmix_proc_t proc;
209 } participant_t;
210 PMIX_CLASS_DECLARATION(participant_t);
211
212 typedef struct {
213 pmix_list_item_t super;
214 int key_idx;
215 } key_replace_t;
216 PMIX_CLASS_DECLARATION(key_replace_t);
217
218 extern pmix_list_t test_fences;
219 extern pmix_list_t *noise_range;
220 extern pmix_list_t key_replace;
221
222 #define NODE_NAME "node1"
223 int get_total_ns_number(test_params params);
224 int get_all_ranks_from_namespace(test_params params, char *nspace, pmix_proc_t **ranks, size_t *nranks);
225
226 typedef struct {
227 int in_progress;
228 pmix_value_t *kv;
229 int status;
230 } get_cbdata;
231
232 #define SET_KEY(key, fence_num, ind, use_same_keys) do { \
233 if (use_same_keys) { \
234 (void)snprintf(key, sizeof(key)-1, "key-%d", ind); \
235 } else { \
236 (void)snprintf(key, sizeof(key)-1, "key-f%d:%d", fence_num, ind); \
237 } \
238 } while (0)
239
240 #define PUT(dtype, data, flag, fence_num, ind, use_same_keys) do { \
241 char key[50]; \
242 pmix_value_t value; \
243 SET_KEY(key, fence_num, ind, use_same_keys); \
244 PMIX_VAL_SET(&value, dtype, data); \
245 TEST_VERBOSE(("%s:%d put key %s", my_nspace, my_rank, key)); \
246 if (PMIX_SUCCESS != (rc = PMIx_Put(flag, key, &value))) { \
247 TEST_ERROR(("%s:%d: PMIx_Put key %s failed: %d", my_nspace, my_rank, key, rc)); \
248 rc = PMIX_ERROR; \
249 } \
250 PMIX_VALUE_DESTRUCT(&value); \
251 } while (0)
252
253 #define GET(dtype, data, ns, r, fence_num, ind, use_same_keys, blocking, ok_notfnd) do { \
254 char key[50]; \
255 pmix_value_t *val; \
256 get_cbdata cbdata; \
257 cbdata.status = PMIX_SUCCESS; \
258 pmix_proc_t foobar; \
259 SET_KEY(key, fence_num, ind, use_same_keys); \
260 (void)strncpy(foobar.nspace, ns, PMIX_MAX_NSLEN); \
261 foobar.rank = r; \
262 TEST_VERBOSE(("%s:%d want to get from %s:%d key %s", my_nspace, my_rank, ns, r, key)); \
263 if (blocking) { \
264 if (PMIX_SUCCESS != (rc = PMIx_Get(&foobar, key, NULL, 0, &val))) { \
265 if( !( (rc == PMIX_ERR_NOT_FOUND || rc == PMIX_ERR_PROC_ENTRY_NOT_FOUND) && ok_notfnd ) ){ \
266 TEST_ERROR(("%s:%d: PMIx_Get failed: %d from %s:%d, key %s", my_nspace, my_rank, rc, ns, r, key)); \
267 } \
268 rc = PMIX_ERROR; \
269 } \
270 } else { \
271 int count; \
272 cbdata.in_progress = 1; \
273 PMIX_VALUE_CREATE(val, 1); \
274 cbdata.kv = val; \
275 if (PMIX_SUCCESS != (rc = PMIx_Get_nb(&foobar, key, NULL, 0, get_cb, (void*)&cbdata))) { \
276 TEST_VERBOSE(("%s:%d: PMIx_Get_nb failed: %d from %s:%d, key=%s", my_nspace, my_rank, rc, ns, r, key)); \
277 rc = PMIX_ERROR; \
278 } else { \
279 count = 0; \
280 while(cbdata.in_progress){ \
281 struct timespec ts; \
282 ts.tv_sec = 0; \
283 ts.tv_nsec = 100; \
284 nanosleep(&ts,NULL); \
285 count++; \
286 } \
287 PMIX_ACQUIRE_OBJECT(&cbdata); \
288 } \
289 } \
290 if (PMIX_SUCCESS == rc) { \
291 if( PMIX_SUCCESS != cbdata.status ){ \
292 if( !( (cbdata.status == PMIX_ERR_NOT_FOUND || cbdata.status == PMIX_ERR_PROC_ENTRY_NOT_FOUND) && ok_notfnd ) ){ \
293 TEST_ERROR(("%s:%d: PMIx_Get_nb failed: %d from %s:%d, key=%s", \
294 my_nspace, my_rank, rc, my_nspace, r)); \
295 } \
296 rc = PMIX_ERROR; \
297 } else if (NULL == val) { \
298 TEST_VERBOSE(("%s:%d: PMIx_Get returned NULL value", my_nspace, my_rank)); \
299 rc = PMIX_ERROR; \
300 } \
301 else if (val->type != PMIX_VAL_TYPE_ ## dtype || PMIX_VAL_CMP(dtype, PMIX_VAL_FIELD_ ## dtype((val)), data)) { \
302 TEST_ERROR(("%s:%u: from %s:%d Key %s value or type mismatch," \
303 " want type %d get type %d", \
304 my_nspace, my_rank, ns, r, key, PMIX_VAL_TYPE_ ## dtype, val->type)); \
305 rc = PMIX_ERROR; \
306 } \
307 } \
308 if (PMIX_SUCCESS == rc) { \
309 TEST_VERBOSE(("%s:%d: GET OF %s from %s:%d SUCCEEDED", my_nspace, my_rank, key, ns, r)); \
310 PMIX_VALUE_RELEASE(val); \
311 } \
312 } while (0)
313
314 #define FENCE(blocking, data_ex, pcs, nprocs) do { \
315 if( blocking ){ \
316 pmix_info_t *info = NULL; \
317 size_t ninfo = 0; \
318 if (data_ex) { \
319 bool value = 1; \
320 PMIX_INFO_CREATE(info, 1); \
321 (void)strncpy(info->key, PMIX_COLLECT_DATA, PMIX_MAX_KEYLEN); \
322 pmix_value_load(&info->value, &value, PMIX_BOOL); \
323 ninfo = 1; \
324 } \
325 rc = PMIx_Fence(pcs, nprocs, info, ninfo); \
326 PMIX_INFO_FREE(info, ninfo); \
327 } else { \
328 int in_progress = 1, count; \
329 rc = PMIx_Fence_nb(pcs, nprocs, NULL, 0, release_cb, &in_progress); \
330 if ( PMIX_SUCCESS == rc ) { \
331 count = 0; \
332 while( in_progress ){ \
333 struct timespec ts; \
334 ts.tv_sec = 0; \
335 ts.tv_nsec = 100; \
336 nanosleep(&ts,NULL); \
337 count++; \
338 } \
339 TEST_VERBOSE(("PMIx_Fence_nb(barrier,collect): free time: %lfs", \
340 count*100*1E-9)); \
341 } \
342 } \
343 if (PMIX_SUCCESS == rc) { \
344 TEST_VERBOSE(("%s:%d: Fence successfully completed", \
345 my_nspace, my_rank)); \
346 } \
347 } while (0)
348
349
350
351
352 #define PMIX_VAL_FIELD_int(x) ((x)->data.integer)
353 #define PMIX_VAL_FIELD_uint32_t(x) ((x)->data.uint32)
354 #define PMIX_VAL_FIELD_uint16_t(x) ((x)->data.uint16)
355 #define PMIX_VAL_FIELD_string(x) ((x)->data.string)
356 #define PMIX_VAL_FIELD_float(x) ((x)->data.fval)
357 #define PMIX_VAL_FIELD_byte(x) ((x)->data.byte)
358 #define PMIX_VAL_FIELD_flag(x) ((x)->data.flag)
359
360 #define PMIX_VAL_TYPE_int PMIX_INT
361 #define PMIX_VAL_TYPE_uint32_t PMIX_UINT32
362 #define PMIX_VAL_TYPE_uint16_t PMIX_UINT16
363 #define PMIX_VAL_TYPE_string PMIX_STRING
364 #define PMIX_VAL_TYPE_float PMIX_FLOAT
365 #define PMIX_VAL_TYPE_byte PMIX_BYTE
366 #define PMIX_VAL_TYPE_flag PMIX_BOOL
367
368 #define PMIX_VAL_set_assign(_v, _field, _val ) \
369 do { \
370 (_v)->type = PMIX_VAL_TYPE_ ## _field; \
371 PMIX_VAL_FIELD_ ## _field((_v)) = _val; \
372 } while (0)
373
374 #define PMIX_VAL_set_strdup(_v, _field, _val ) \
375 do { \
376 (_v)->type = PMIX_VAL_TYPE_ ## _field; \
377 PMIX_VAL_FIELD_ ## _field((_v)) = strdup(_val); \
378 } while (0)
379
380 #define PMIX_VAL_SET_int PMIX_VAL_set_assign
381 #define PMIX_VAL_SET_uint32_t PMIX_VAL_set_assign
382 #define PMIX_VAL_SET_uint16_t PMIX_VAL_set_assign
383 #define PMIX_VAL_SET_string PMIX_VAL_set_strdup
384 #define PMIX_VAL_SET_float PMIX_VAL_set_assign
385 #define PMIX_VAL_SET_byte PMIX_VAL_set_assign
386 #define PMIX_VAL_SET_flag PMIX_VAL_set_assign
387
388 #define PMIX_VAL_SET(_v, _field, _val ) \
389 PMIX_VAL_SET_ ## _field(_v, _field, _val)
390
391 #define PMIX_VAL_cmp_val(_val1, _val2) ((_val1) != (_val2))
392 #define PMIX_VAL_cmp_float(_val1, _val2) (((_val1)>(_val2))?(((_val1)-(_val2))>0.000001):(((_val2)-(_val1))>0.000001))
393 #define PMIX_VAL_cmp_ptr(_val1, _val2) strncmp(_val1, _val2, strlen(_val1)+1)
394
395 #define PMIX_VAL_CMP_int PMIX_VAL_cmp_val
396 #define PMIX_VAL_CMP_uint32_t PMIX_VAL_cmp_val
397 #define PMIX_VAL_CMP_uint16_t PMIX_VAL_cmp_val
398 #define PMIX_VAL_CMP_float PMIX_VAL_cmp_float
399 #define PMIX_VAL_CMP_string PMIX_VAL_cmp_ptr
400 #define PMIX_VAL_CMP_byte PMIX_VAL_cmp_val
401 #define PMIX_VAL_CMP_flag PMIX_VAL_cmp_val
402
403 #define PMIX_VAL_ASSIGN(_v, _field, _val) \
404 PMIX_VAL_set_assign(_v, _field, _val)
405
406 #define PMIX_VAL_CMP(_field, _val1, _val2) \
407 PMIX_VAL_CMP_ ## _field(_val1, _val2)
408
409 #define PMIX_VAL_FREE(_v) \
410 PMIx_free_value_data(_v)
411
412 #endif