1 /* $Id: test_ncbi_linkerd.c 575619 2018-12-02 03:24:59Z mcelhany $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Authors: David McElhany
27 *
28 * File Description:
29 * Standard test for LINKERD service resolution facility.
30 *
31 */
32
33
34 #include "../ncbi_ansi_ext.h"
35 #include "../ncbi_priv.h" /* CORE logging facilities */
36 #include "../ncbi_linkerd.h"
37 #include "../ncbi_servicep.h"
38 #include "../parson.h"
39
40 #include <connect/ncbi_server_info.h>
41 #include <connect/ncbi_service.h>
42 #include <connect/ncbi_tls.h>
43
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <time.h>
48
49
50 /* ---------------------------------------------------------------------------
51 Stub out the whole program for Windows DLL configurations.
52 The problem is that the program uses PARSON, which does not have the
53 dllexport/dllimport specifiers, resulting in link errors when built
54 with DLL on Windows.
55 */
56 #if defined(NCBI_OS_MSWIN) && defined(NCBI_DLL_BUILD)
main(int argc,const char * argv[])57 int main(int argc, const char *argv[])
58 {
59 printf("NCBI_UNITTEST_DISABLED - This program is disabled for WinDLL.\n");
60 return 1;
61 }
62 #else
63
64 #ifdef _MSC_VER
65 #define unsetenv(n) _putenv_s(n,"")
66 #define setenv(n,v,w) _putenv_s(n,v)
67 #define FMT_SIZE_T "%llu"
68 #else
69 #define FMT_SIZE_T "%zu"
70 #endif
71
72 #define LEN_HOST 77
73 #define LEN_HDR 99
74 #define MAX_TESTS 100
75
76 #define NIL '\0'
77
78
79 /* ----------------------------------------------------------------------------
80 Local Types
81 */
82
83 typedef struct
84 {
85 char host[LEN_HOST+1];
86 char hdr [LEN_HDR +1];
87 unsigned short port;
88 } SEndpoint;
89
90 typedef enum {
91 fMatch_None = 0,
92 fMatch_Host = 0x01,
93 fMatch_Port = 0x02,
94 fMatch_Hdr = 0x04,
95 fMatch_All = -1,
96 fMatch_Default = fMatch_All
97 } EMatch;
98
99 typedef struct
100 {
101 const char* name;
102 const char* result;
103 } STestResult;
104
105
106
107
108 /* ----------------------------------------------------------------------------
109 Static Variables
110 */
111
112 static SEndpoint s_end_exp;
113 static SEndpoint s_end_got;
114 static const char* s_json_file = "test_ncbi_linkerd_tests.json";
115 static STestResult s_results[MAX_TESTS];
116
117
118
119
120 /* ----------------------------------------------------------------------------
121 Static Function Declarations
122 */
123
124 static int check_match(EMatch flags);
125
126 static int run_a_test(size_t test_idx, const char *svc, const char *sch,
127 const char *user, const char *pass, const char *path,
128 const char *args, int exp_err, int exp_warn, int repop,
129 int reset);
130
131 static int run_tests(const char *test_nums);
132
133
134
135
136 /* ----------------------------------------------------------------------------
137 Static Functions
138 */
139
check_match(EMatch flags)140 static int check_match(EMatch flags)
141 {
142 if ((flags & fMatch_Host) && strcmp(s_end_exp.host, s_end_got.host) != 0) {
143 /* always consider localhost a match */
144 if (strcmp("127.0.0.1", s_end_got.host) != 0)
145 return 0;
146 }
147
148 if ((flags & fMatch_Hdr) && strcmp(s_end_exp.hdr, s_end_got.hdr) != 0)
149 return 0;
150
151 if ((flags & fMatch_Port) && s_end_exp.port != s_end_got.port)
152 return 0;
153
154 return 1;
155 }
156
157
run_a_test(size_t test_idx,const char * svc,const char * sch,const char * user,const char * pass,const char * path,const char * args,int exp_err,int exp_warn,int repop,int reset)158 static int run_a_test(size_t test_idx, const char *svc, const char *sch,
159 const char *user, const char *pass, const char *path,
160 const char *args, int exp_err, int exp_warn, int repop,
161 int reset)
162 {
163 const SSERV_Info *info = NULL;
164 SConnNetInfo *net_info;
165 SERV_ITER iter;
166 int success = 0, errors = 0;
167 int retval = -1;
168
169 /* Set up the net_info */
170 if ( ! svc) {
171 CORE_LOG(eLOG_Critical, "Unexpected empty service name.");
172 return 0;
173 }
174 net_info = ConnNetInfo_Create(svc);
175 if (sch) {
176 if (strcasecmp(sch, "http" ) == 0) net_info->scheme = eURL_Http;
177 else if (strcasecmp(sch, "https") == 0) net_info->scheme = eURL_Https;
178 else {
179 CORE_LOG(eLOG_Critical, "Unexpected non-http(s) scheme.");
180 CORE_LOG(eLOG_Note, "Test result: FAIL.");
181 return 0;
182 }
183 }
184 if (user && strlen(user) >= sizeof(net_info->user)) {
185 CORE_LOG(eLOG_Critical, "Unexpected too-long user.");
186 CORE_LOG(eLOG_Note, "Test result: FAIL.");
187 return 0;
188 }
189 if (pass && strlen(pass) >= sizeof(net_info->pass)) {
190 CORE_LOG(eLOG_Critical, "Unexpected too-long password.");
191 CORE_LOG(eLOG_Note, "Test result: FAIL.");
192 return 0;
193 }
194 if ((path ? strlen(path) : 0) + 1 +
195 (args ? strlen(args) : 0) >= sizeof(net_info->path))
196 {
197 CORE_LOG(eLOG_Critical, "Unexpected too-long path / args.");
198 CORE_LOG(eLOG_Note, "Test result: FAIL.");
199 return 0;
200 }
201 strcpy(net_info->user, user ? user : "");
202 strcpy(net_info->pass, pass ? pass : "");
203 ConnNetInfo_SetPath(net_info, path ? path : "");
204 ConnNetInfo_SetArgs(net_info, args ? args : "");
205
206 /* Set up the server iterator */
207 iter = SERV_OpenP(svc, fSERV_All |
208 (strpbrk(svc, "?*") ? fSERV_Promiscuous : 0),
209 SERV_LOCALHOST, 0/*port*/, 0.0/*preference*/,
210 net_info, 0/*skip*/, 0/*n_skip*/,
211 0/*external*/, 0/*arg*/, 0/*val*/);
212 ConnNetInfo_Destroy(net_info);
213
214 /* Fetch the linkerd info */
215 if ( ! iter) {
216 CORE_LOG(eLOG_Error, "SERV_OpenP failed.");
217 errors = 1;
218 } else {
219 info = SERV_GetNextInfo(iter);
220 if ( ! info) {
221 CORE_LOG(eLOG_Error, "SERV_GetNextInfo failed.");
222 errors = 1;
223 } else {
224 SOCK_ntoa(info->host, s_end_got.host, LEN_HOST);
225 s_end_got.port = info->port;
226 /* s_end_got.hdr is not currently set because it isn't strictly
227 needed for comparison (plus it would be very ugly code) */
228
229 char *info_str;
230 info_str = SERV_WriteInfo(info);
231 CORE_LOGF(eLOG_Note, (" Found server: %s",
232 info_str ? info_str : "?"));
233 if (info_str)
234 free(info_str);
235 /* linkerd must return only 1 hit */
236 info = SERV_GetNextInfo(iter);
237 if (info) {
238 CORE_LOG(eLOG_Error, "linkerd unexpectedly returned a hit.");
239 errors = 1;
240 } else {
241
242 /* Make sure endpoint data can be repopulated and reset */
243 if (repop) {
244 /* repopulate */
245 CORE_LOG(eLOG_Trace, "Repopulating the service mapper.");
246 if ( ! SERV_GetNextInfo(iter)) {
247 CORE_LOG(eLOG_Error, "Unable to repopulate endpoint data.");
248 errors = 1;
249 }
250 }
251 if (reset) {
252 /* reset */
253 CORE_LOG(eLOG_Trace, "Resetting the service mapper.");
254 SERV_Reset(iter);
255 if ( ! SERV_GetNextInfo(iter)) {
256 CORE_LOG(eLOG_Error, "No services found after reset.");
257 errors = 1;
258 }
259 }
260 }
261
262 SERV_Close(iter);
263 }
264 }
265
266 /* Check for match */
267 /* Note that the host IP may change, and the header isn't parsed,
268 so currently only the port is checked - but that is a
269 reserved port, so it should be sufficient. */
270 if (check_match(fMatch_Port)) {
271 CORE_LOG(eLOG_Note, " Found server matched expected server.");
272 if ( ! errors)
273 success = 1;
274 } else {
275 CORE_LOG(eLOG_Note, " Found server didn't match expected server.");
276 }
277
278 retval = (success != exp_err ? 1 : 0);
279 CORE_LOGF(eLOG_Note, ("Test result: %s.",
280 retval ?
281 (success ? "PASS" : "PASS (with expected error)") :
282 (success ? "FAIL (success when error expected)" : "FAIL")));
283
284 return retval;
285 }
286
287
288 /* wrapper around x_json_object_dotget_string() to support platform-specific
289 overrides */
p_json_object_dotget_string(x_JSON_Object * obj,const char * path)290 static const char * p_json_object_dotget_string(x_JSON_Object *obj,
291 const char *path)
292 {
293 #define PLATFORM_BUFLEN 200
294 char platform_buf[PLATFORM_BUFLEN+1];
295 const char *platform = NULL;
296 const char *val;
297
298 #if defined(NCBI_OS_MSWIN)
299 platform = "win";
300 #elif defined(NCBI_OS_UNIX)
301 platform = "nix";
302 #endif
303 if (platform) {
304 if (strlen(path) + strlen(platform) + 1 > PLATFORM_BUFLEN) {
305 strncpy(platform_buf, path, PLATFORM_BUFLEN);
306 platform_buf[PLATFORM_BUFLEN] = NIL;
307 CORE_LOGF(eLOG_Error, ("Overlong path: '%s'...", platform_buf));
308 }
309 sprintf(platform_buf, "%s_%s", path, platform);
310 val = x_json_object_dotget_string(obj, platform_buf);
311 if (val)
312 return val;
313 }
314 return x_json_object_dotget_string(obj, path);
315 #undef PLATFORM_BUFLEN
316 }
317
318
319 /* mostly error-handling-free for the moment :-/ */
run_tests(const char * test_nums)320 static int run_tests(const char *test_nums)
321 {
322 x_JSON_Value *root_value = NULL;
323 x_JSON_Object *root_obj;
324 x_JSON_Array *test_arr;
325 const char *test_num = test_nums;
326 size_t n_tests = 0, n_pass = 0, n_fail = 0, n_skip = 0;
327 size_t n_comm_unset, n_comm_set;
328 int all_enabled = 0;
329 const char *cmn_svc = NULL, *cmn_sch = NULL;
330 const char *cmn_user = NULL, *cmn_pass = NULL;
331 const char *cmn_path = NULL, *cmn_args = NULL;
332 const char *cmn_exp_host = NULL, *cmn_exp_hdr = NULL;
333 unsigned short cmn_exp_port = 0;
334
335
336 CORE_LOG(eLOG_Note,
337 "============================================================");
338 CORE_LOGF(eLOG_Note, ("Test file: %s", s_json_file));
339
340 root_value = x_json_parse_file(s_json_file);
341 root_obj = x_json_value_get_object(root_value);
342
343 if (x_json_object_has_value_of_type(root_obj, "all_enabled", JSONNumber) &&
344 (int)x_json_object_get_number(root_obj, "all_enabled") != 0)
345 {
346 all_enabled = 1;
347 }
348
349 cmn_svc = p_json_object_dotget_string(root_obj, "common.service");
350 cmn_sch = p_json_object_dotget_string(root_obj, "common.scheme");
351 cmn_user = p_json_object_dotget_string(root_obj, "common.user");
352 cmn_pass = p_json_object_dotget_string(root_obj, "common.pass");
353 cmn_path = p_json_object_dotget_string(root_obj, "common.path");
354 cmn_args = p_json_object_dotget_string(root_obj, "common.args");
355
356 cmn_exp_host = p_json_object_dotget_string(root_obj, "common.expect.host");
357 cmn_exp_hdr = p_json_object_dotget_string(root_obj,
358 "common.expect.host_hdr");
359 cmn_exp_port = (unsigned short)x_json_object_dotget_number(root_obj,
360 "common.expect.port");
361
362 test_arr = x_json_object_get_array(root_obj, "tests");
363 n_tests = x_json_array_get_count(test_arr);
364 if ( ! (n_tests == x_json_array_get_count(test_arr))) {
365 CORE_LOG(eLOG_Critical, "JSON array count mismatch.");
366 return 0;
367 }
368 size_t it;
369 for (it = 0; it < n_tests; ++it) {
370 x_JSON_Object *test_obj;
371 const char *svc = NULL, *sch = NULL;
372 const char *user = NULL, *pass = NULL;
373 const char *path = NULL, *args = NULL;
374 const char *exp_host = NULL, *exp_hdr = NULL;
375 unsigned short exp_port = 0;
376 int err = 0, warn = 0;
377
378 test_obj = x_json_array_get_object(test_arr, it);
379 s_results[it].name = x_json_object_get_string(test_obj, "title");
380
381 /* Skip tests not in user-supplied test numbers list */
382 if (test_nums && *test_nums) {
383 size_t next_test;
384 if ( ! test_num)
385 break;
386 if (sscanf(test_num, FMT_SIZE_T, &next_test) == 1) {
387 if (it+1 != next_test) {
388 s_results[it].result = "-";
389 continue;
390 } else {
391 test_num = strchr(test_num, ',');
392 if (test_num && *test_num)
393 test_num++;
394 }
395 } else {
396 CORE_LOGF(eLOG_Error, ("Invalid test numbers list: %s",
397 test_num));
398 return 0;
399 }
400 }
401
402 CORE_LOG(eLOG_Note,
403 "============================================================");
404
405 /* Skip disabled tests */
406 if ( ! all_enabled) {
407 if (x_json_object_has_value_of_type(test_obj, "disabled",
408 JSONNumber))
409 {
410 if ((int)x_json_object_get_number(test_obj, "disabled") == 1) {
411 ++n_skip;
412 CORE_LOGF(eLOG_Note, ("Skipping test " FMT_SIZE_T ": %s",
413 it+1, x_json_object_get_string(test_obj, "title")));
414 s_results[it].result = "skip";
415 continue;
416 }
417 }
418 }
419
420 CORE_LOGF(eLOG_Note, ("Running test " FMT_SIZE_T ": %s", it+1,
421 s_results[it].name));
422
423 svc = x_json_object_get_string(test_obj, "service");
424 sch = x_json_object_get_string(test_obj, "scheme");
425 user = x_json_object_get_string(test_obj, "user");
426 pass = x_json_object_get_string(test_obj, "pass");
427 path = x_json_object_get_string(test_obj, "path");
428 args = x_json_object_get_string(test_obj, "args");
429
430 exp_host = p_json_object_dotget_string(test_obj, "expect.host");
431 exp_hdr = p_json_object_dotget_string(test_obj, "expect.hdr");
432 exp_port = (unsigned short)x_json_object_dotget_number(test_obj,
433 "expect.port");
434
435 if ( ! svc ) svc = cmn_svc;
436 if ( ! sch ) sch = cmn_sch;
437 if ( ! user) user = cmn_user;
438 if ( ! pass) pass = cmn_pass;
439 if ( ! path) path = cmn_path;
440 if ( ! args) path = cmn_args;
441
442 if ( ! exp_host) exp_host = cmn_exp_host;
443 if ( ! exp_hdr ) exp_hdr = cmn_exp_hdr;
444 if ( ! exp_port) exp_port = cmn_exp_port;
445
446 if (x_json_object_has_value_of_type(test_obj, "expect_error",
447 JSONString))
448 {
449 if (strcmp(x_json_object_get_string(test_obj, "expect_error"),
450 "yes") == 0)
451 {
452 err = 1;
453 }
454 }
455
456 if (x_json_object_has_value_of_type(test_obj, "expect_warn",
457 JSONString))
458 {
459 if (strcmp(x_json_object_get_string(test_obj, "expect_warn"),
460 "yes") == 0)
461 {
462 /* LINKERD_TODO - compare exp warn to got warn;
463 add to determination of success */
464 warn = 1;
465 }
466 }
467
468 const char *msg_svc = svc ? svc : "(not set)";
469 const char *msg_sch = sch ? sch : "(not set)";
470 const char *msg_user = user ? user : "(not set)";
471 const char *msg_pass = pass ? pass : "(not set)";
472 const char *msg_path = path ? path : "(not set)";
473 const char *msg_args = args ? args : "(not set)";
474 const char *msg_exp_host = exp_host ? exp_host : "(not set)";
475 const char *msg_exp_hdr = exp_hdr ? exp_hdr : "(not set)";
476 const char *msg_err = err ? "yes" : "no";
477 const char *msg_warn = warn ? "yes" : "no";
478 CORE_LOGF(eLOG_Note, (" service: %s", msg_svc ));
479 CORE_LOGF(eLOG_Note, (" scheme: %s", msg_sch ));
480 CORE_LOGF(eLOG_Note, (" user: %s", msg_user ));
481 CORE_LOGF(eLOG_Note, (" password: %s", msg_pass ));
482 CORE_LOGF(eLOG_Note, (" path: %s", msg_path ));
483 CORE_LOGF(eLOG_Note, (" args: %s", msg_args ));
484 CORE_LOGF(eLOG_Note, (" expected host: %s", msg_exp_host));
485 CORE_LOGF(eLOG_Note, (" expected header: %s", msg_exp_hdr ));
486 CORE_LOGF(eLOG_Note, (" expected port: %hu", exp_port ));
487 CORE_LOGF(eLOG_Note, (" expected error: %s", msg_err ));
488 CORE_LOGF(eLOG_Note, (" expected warning: %s", msg_warn ));
489
490 /* Redo common unset/set - they could have been changed by a prior
491 test */
492 if (x_json_object_dothas_value_of_type(root_obj, "common.env_unset",
493 JSONArray))
494 {
495 x_JSON_Array *comm_unset_arr;
496
497 comm_unset_arr = x_json_object_dotget_array(root_obj,
498 "common.env_unset");
499 n_comm_unset = x_json_array_get_count(comm_unset_arr);
500
501 size_t it2;
502 for (it2 = 0; it2 < n_comm_unset; ++it2) {
503 const char *name = x_json_array_get_string(
504 comm_unset_arr, it2);
505
506 CORE_LOGF(eLOG_Note, (" Unsetting common var: %s", name));
507 unsetenv(name);
508 if (getenv(name) != NULL) {
509 CORE_LOGF(eLOG_Critical,
510 ("Unable to unset common env var %s.", name));
511 return 0;
512 }
513 }
514 }
515 if (x_json_object_dothas_value_of_type(root_obj, "common.env_set",
516 JSONArray))
517 {
518 x_JSON_Array *comm_set_arr;
519
520 comm_set_arr = x_json_object_dotget_array(root_obj,
521 "common.env_set");
522 n_comm_set = x_json_array_get_count(comm_set_arr);
523
524 size_t it2;
525 for (it2 = 0; it2 < n_comm_set; ++it2) {
526 x_JSON_Object *env_obj = x_json_array_get_object(comm_set_arr,
527 it2);
528 const char *name = x_json_object_get_name(env_obj, 0);
529 const char *val = x_json_value_get_string(
530 x_json_object_get_value_at(env_obj, 0));
531
532 CORE_LOGF(eLOG_Note, (" Setting common var: %s=%s", name,
533 val));
534 setenv(name, val, 1);
535 if (strcmp(val, getenv(name)) != 0) {
536 CORE_LOGF(eLOG_Critical,
537 ("Unable to set common env var %s to '%s'.",
538 name, val));
539 return 0;
540 }
541 }
542 }
543
544 /* Per-test unset/set */
545 if (x_json_object_has_value_of_type(test_obj, "env_unset", JSONArray)) {
546 x_JSON_Array *unset_arr;
547 size_t n_unset;
548
549 unset_arr = x_json_object_get_array(test_obj, "env_unset");
550 n_unset = x_json_array_get_count(unset_arr);
551 CORE_LOGF(eLOG_Note, (
552 " Unset per-test environment variables: " FMT_SIZE_T,
553 n_unset));
554 if (n_unset) {
555 size_t it2;
556 for (it2 = 0; it2 < n_unset; ++it2) {
557 const char *name = x_json_array_get_string(unset_arr, it2);
558
559 CORE_LOGF(eLOG_Note, (" %s", name));
560 unsetenv(name);
561 if (getenv(name) != NULL) {
562 CORE_LOGF(eLOG_Critical,
563 ("Unable to unset per-test env var %s.", name));
564 return 0;
565 }
566 }
567 }
568 }
569 if (x_json_object_has_value_of_type(test_obj, "env_set", JSONArray)) {
570 x_JSON_Array *set_arr;
571 size_t n_set;
572
573 set_arr = x_json_object_get_array(test_obj, "env_set");
574 n_set = x_json_array_get_count(set_arr);
575 CORE_LOGF(eLOG_Note, (
576 " Set per-test environment variables: " FMT_SIZE_T,
577 n_set));
578 if (n_set) {
579 size_t it2;
580 for (it2 = 0; it2 < n_set; ++it2) {
581 x_JSON_Object *env_obj = x_json_array_get_object(set_arr,
582 it2);
583 const char *name = x_json_object_get_name(env_obj, 0);
584 const char *val = x_json_value_get_string(
585 x_json_object_get_value_at(env_obj, 0));
586
587 CORE_LOGF(eLOG_Note, (" %s=%s", name, val));
588 setenv(name, val, 1);
589 if (strcmp(val, getenv(name)) != 0) {
590 CORE_LOGF(eLOG_Critical,
591 ("Unable to set per-test env var %s to '%s'.",
592 name, val));
593 return 0;
594 }
595 }
596 }
597 }
598
599 if (strlen(exp_host) > LEN_HOST) {
600 CORE_LOG(eLOG_Critical, "Too-long exp_host.");
601 return 0;
602 }
603 if (strlen(exp_hdr) > LEN_HDR) {
604 CORE_LOG(eLOG_Critical, "Too-long exp_hdr.");
605 return 0;
606 }
607 strcpy(s_end_exp.host, exp_host);
608 strcpy(s_end_exp.hdr , exp_hdr);
609 s_end_exp.port = exp_port;
610
611 CORE_LOGF(eLOG_Note, (
612 " Expected server: %s:%hu %s",
613 s_end_exp.host, s_end_exp.port, s_end_exp.hdr));
614
615 int repop = 0, reset = 0;
616 if (x_json_object_has_value_of_type(
617 test_obj, "iter-repop", JSONString) &&
618 strcmp(x_json_object_get_string(
619 test_obj, "iter-repop"), "yes") == 0)
620 {
621 repop = 1;
622 }
623 if (x_json_object_has_value_of_type(
624 test_obj, "iter-reset", JSONString) &&
625 strcmp(x_json_object_get_string(
626 test_obj, "iter-reset"), "yes") == 0)
627 {
628 reset = 1;
629 }
630
631 /* Run the test */
632 if (run_a_test(it, svc, sch, user, pass, path, args, err, warn, repop,
633 reset))
634 {
635 ++n_pass;
636 s_results[it].result = "ok";
637 } else {
638 ++n_fail;
639 s_results[it].result = "FAIL";
640 }
641 }
642
643 CORE_LOG (eLOG_Note,
644 "============================================================");
645 CORE_LOGF(eLOG_Note,
646 (FMT_SIZE_T " tests: " FMT_SIZE_T " passed, "
647 FMT_SIZE_T " failed, " FMT_SIZE_T " skipped",
648 n_tests, n_pass, n_fail, n_skip));
649 CORE_LOG (eLOG_Note,
650 "============================================================");
651 CORE_LOG (eLOG_Note,
652 "Test Result Description");
653 CORE_LOG (eLOG_Note,
654 "---- ------ ----------------------------------------------");
655 for (it = 0; it < n_tests; ++it) {
656 if ( ! s_results[it].result || ! *s_results[it].result ||
657 *s_results[it].result == '-')
658 {
659 continue;
660 }
661 char tests_buf[6];
662 if (it+1 > 9999)
663 strcpy (tests_buf, "####");
664 else
665 sprintf(tests_buf, FMT_SIZE_T, it+1);
666 CORE_LOGF(eLOG_Note, ("%4s %6s %s",
667 tests_buf, s_results[it].result, s_results[it].name));
668 }
669
670 if (root_value)
671 x_json_value_free(root_value);
672
673 return (n_tests > 0 && n_pass == n_tests - n_skip) ? 1 : 0;
674 }
675
676
677
678
679 /* ----------------------------------------------------------------------------
680 Main
681 */
682
main(int argc,const char * argv[])683 int main(int argc, const char *argv[])
684 {
685 const char *retmsg = "";
686 const char *test_nums = "";
687 int retval = 1;
688
689 int i;
690 for (i=1; i < argc; ++i) {
691 if (strcmp(argv[i], "-f") == 0 && i < argc-1) {
692 ++i;
693 s_json_file = argv[i];
694 } else if (strcmp(argv[i], "-n") == 0 && i < argc-1) {
695 ++i;
696 test_nums = argv[i];
697 retmsg = "Not all tests run.";
698 } else {
699 fprintf(stderr, "USAGE: %s [OPTIONS...]\n", argv[0]);
700 fprintf(stderr,
701 " [-h] help\n"
702 " [-f ARG] test file\n"
703 " [-n ARG] comma-separated test selections (eg 1,2,5)\n");
704 goto out;
705 }
706 }
707
708 CORE_SetLOGFormatFlags(fLOG_None | fLOG_Level | fLOG_OmitNoteLevel);
709 CORE_SetLOGFILE(stderr, 0/*false*/);
710
711 SOCK_SetupSSL(NcbiSetupTls);
712
713 if ( ! run_tests(test_nums) && ! *retmsg)
714 retmsg = "Not all tests passed.";
715
716 out:
717 CORE_LOG(eLOG_Note, "");
718 if (strcmp(retmsg, "") == 0) {
719 /* The only successful condition is a run of all tests */
720 CORE_LOG(eLOG_Note, "SUCCESS - All tests passed.");
721 retval = 0;
722 } else {
723 CORE_LOGF(eLOG_Note, ("FAIL - %s", retmsg));
724 }
725 CORE_SetLOG(0);
726 return retval;
727 }
728
729
730 /* END -----------------------------------------------------------------------
731 Stub out the program for Windows DLL configurations.
732 */
733 #endif
734