1 #ifndef CONNECT___TEST_NCBI_LBOS__HPP
2 #define CONNECT___TEST_NCBI_LBOS__HPP
3
4 /* $Id: test_ncbi_lbos_common.hpp 617369 2020-09-30 13:00:09Z ucko $
5 * ===========================================================================
6 *
7 * PUBLIC DOMAIN NOTICE
8 * National Center for Biotechnology Information
9 *
10 * This software/database is a "United States Government Work" under the
11 * terms of the United States Copyright Act. It was written as part of
12 * the author's official duties as a United States Government employee and
13 * thus cannot be copyrighted. This software/database is freely available
14 * to the public for use. The National Library of Medicine and the U.S.
15 * Government have not placed any restriction on its use or reproduction.
16 *
17 * Although all reasonable efforts have been taken to ensure the accuracy
18 * and reliability of the software and data, the NLM and the U.S.
19 * Government do not and cannot warrant the performance or results that
20 * may be obtained by using this software or data. The NLM and the U.S.
21 * Government disclaim all warranties, express or implied, including
22 * warranties of performance, merchantability or fitness for any particular
23 * purpose.
24 *
25 * Please cite the author in any work or product based on this material.
26 *
27 * ===========================================================================
28 *
29 * Author: Dmitriy Elisov
30 *
31 * File Description:
32 * Common functions for LBOS mapper tests
33 *
34 */
35
36 /*C++*/
37 #include <sstream>
38 #include <corelib/ncbiapp.hpp>
39 #include <corelib/ncbithr.hpp>
40 #include <corelib/ncbistr.hpp>
41 #include <corelib/ncbi_system.hpp>
42 #include <corelib/ncbifile.hpp>
43 #include <corelib/request_ctx.hpp>
44 #include <connect/ncbi_conn_stream.hpp>
45 #include <connect/ncbi_lbos.hpp>
46 #include <connect/ncbi_monkey.hpp>
47 #include "../ncbi_lbosp.hpp"
48 #include <connect/server.hpp>
49 #include <util/random_gen.hpp>
50 /*C*/
51 #include "../ncbi_ansi_ext.h"
52 #include "../ncbi_lbsmd.h"
53 #include "../ncbi_priv.h" /* CORE logging facilities */
54 #include "../ncbi_lbosp.h"
55
56 //#define BOOST_AUTO_TEST_MAIN
57 /*std*/
58 #include <locale.h>
59 #define _CRT_RAND_S
60 #include <stdlib.h>
61 #undef _CRT_RAND_S
62 #include <time.h>
63 #ifdef NCBI_OS_MSWIN
64 # include <winsock2.h>
65 #else
66 # include <sys/time.h>
67 #endif
68
69
70 /* Boost Test Framework or test_mt */
71 #ifdef LBOS_TEST_MT
72
73 # undef NCBITEST_CHECK_MESSAGE
74 # define NCBITEST_CHECK_MESSAGE(P,M) \
75 { \
76 stringstream ss; \
77 int* p_val = s_Tls->GetValue(); \
78 if (p_val != NULL) \
79 { \
80 ss << "Thread " << *p_val << ": "; \
81 } \
82 ss << M; \
83 if (!(P)) {/* the process is doomed, let's print what was announced */\
84 s_PrintPortsLines(); \
85 s_Print500sCount(); \
86 s_PrintResolutionErrors(); \
87 } \
88 NCBI_ALWAYS_ASSERT(P,ss.str().c_str()); \
89 }
90 # undef NCBITEST_REQUIRE_MESSAGE
91 # define NCBITEST_REQUIRE_MESSAGE(P,M) \
92 NCBITEST_CHECK_MESSAGE(P,M)
93 # undef BOOST_CHECK_EXCEPTION
94 # define BOOST_CHECK_EXCEPTION(S,E,P) \
95 do { \
96 try { \
97 S; \
98 } \
99 catch (const E& ex) { \
100 NCBITEST_CHECK_MESSAGE(P(ex), \
101 "LBOS exception contains wrong error type") \
102 break; \
103 } \
104 catch (...) { \
105 NCBITEST_CHECK_MESSAGE(false, \
106 "Unexpected exception was thrown") \
107 } \
108 NCBITEST_CHECK_MESSAGE(false, \
109 "No exception was thrown") \
110 } while (false);
111 //because assert and exception are the same
112 # undef BOOST_CHECK_NO_THROW
113 # define BOOST_CHECK_NO_THROW(S) S
114 # undef NCBITEST_CHECK_EQUAL
115 # define NCBITEST_CHECK_EQUAL(S,E) \
116 do { \
117 stringstream ss, lh_str, rh_str; \
118 lh_str << S; \
119 rh_str << E; \
120 ss << " (" << #S << " != " << #E << ")" \
121 << " (" << lh_str.str() << " != " << rh_str.str() << ")"; \
122 NCBITEST_CHECK_MESSAGE(lh_str.str() == rh_str.str(), \
123 ss.str().c_str()) \
124 } while(false);
125
126 # undef NCBITEST_CHECK_NE
127 # define NCBITEST_CHECK_NE(S,E) \
128 do { \
129 stringstream ss; \
130 ss << " (" << S << " == " << E << ")"; \
131 NCBITEST_CHECK_MESSAGE(S != E, ss.str().c_str()) \
132 } while(false);
133 # undef NCBITEST_REQUIRE_NE
134 # define NCBITEST_REQUIRE_NE(S,E) \
135 NCBITEST_CHECK_NE(S,E)
136 #else /* if LBOS_TEST_MT not defined */
137 // This header must be included before all Boost.Test headers
138 # include <corelib/test_boost.hpp>
139 #endif /* #ifdef LBOS_TEST_MT */
140
141 #if 0
142
143 #ifdef LBOS_TEST_MT
144 # define NCBITEST_CHECK_MESSAGE(P,M) \
145 NCBITEST_CHECK_MESSAGE(P,M)
146 # define NCBITEST_REQUIRE_MESSAGE(P,M) \
147 NCBITEST_REQUIRE_MESSAGE(P,M)
148 # define BOOST_CHECK_EXCEPTION(S,E,P) \
149 BOOST_CHECK_EXCEPTION(S,E,P)
150 # define BOOST_CHECK_NO_THROW(S) \
151 BOOST_CHECK_NO_THROW(S)
152 # define NCBITEST_CHECK_EQUAL(S,E) \
153 NCBITEST_CHECK_EQUAL(S,E)
154 # define NCBITEST_CHECK_NE(S,E) \
155 NCBITEST_CHECK_NE(S,E)
156 # define NCBITEST_REQUIRE_NE(S,E) \
157 NCBITEST_REQUIRE_NE(S,E)
158 #else /* if LBOS_TEST_MT not defined - no thread output */
159 # define NCBITEST_CHECK_MESSAGE(P,M) \
160 NCBITEST_CHECK_MESSAGE(P,M)
161 # define NCBITEST_REQUIRE_MESSAGE(P,M) \
162 NCBITEST_REQUIRE_MESSAGE(P,M)
163 # define BOOST_CHECK_EXCEPTION(S,E,P) \
164 BOOST_CHECK_EXCEPTION(S,E,P)
165 # define BOOST_CHECK_NO_THROW(S) \
166 BOOST_CHECK_NO_THROW(S)
167 # define NCBITEST_CHECK_EQUAL(S,E) \
168 NCBITEST_CHECK_EQUAL(S,E)
169 # define NCBITEST_CHECK_NE(S,E) \
170 NCBITEST_CHECK_NE(S,E)
171 # define NCBITEST_REQUIRE_NE(S,E) \
172 NCBITEST_REQUIRE_NE(S,E)
173 #endif /* #ifdef LBOS_TEST_MT */
174
175 #endif
176
177 #ifndef NCBITEST_CHECK_MESSAGE_MT_SAFE
178 /* Boost checks are not thread-safe, so they need to be handled appropriately*/
179 # define MT_SAFE(E) \
180 {{ \
181 CFastMutexGuard spawn_guard(s_BoostTestLock); \
182 E; \
183 }}
184 # define NCBITEST_CHECK_MESSAGE_MT_SAFE(P,M) \
185 MT_SAFE(NCBITEST_CHECK_MESSAGE(P, M))
186 # define NCBITEST_REQUIRE_MESSAGE_MT_SAFE(P,M) \
187 MT_SAFE(NCBITEST_REQUIRE_MESSAGE(P, M))
188 # define NCBITEST_CHECK_EQUAL_MT_SAFE(S,E) \
189 MT_SAFE(NCBITEST_CHECK_EQUAL(S, E))
190 # define NCBITEST_CHECK_NE_MT_SAFE(S,E) \
191 MT_SAFE(NCBITEST_CHECK_NE(S, E))
192 # define NCBITEST_REQUIRE_NE_MT_SAFE(S,E) \
193 MT_SAFE(NCBITEST_REQUIRE_NE(S, E))
194 #endif
195
196 #ifdef LBOS_TEST_MT
197 #define TEST_PASS return
198 #define EXTRACT_TEST_NAME \
199 size_t first_colon = func_name.find(':') + 2; \
200 size_t last_colon = func_name.find_last_of(':') - 1; \
201 func_name = func_name.substr(first_colon, last_colon - first_colon);
202 #else
203 #define TEST_PASS return
204 #define EXTRACT_TEST_NAME
205 #endif
206
207 #define CHECK_LBOS_VERSION() \
208 do { \
209 string func_name = __FUNCTION__; \
210 EXTRACT_TEST_NAME \
211 CCObjHolder<char> versions_cstr(g_LBOS_RegGet("TESTVERSIONS", \
212 func_name.c_str(), \
213 NULL)); \
214 if (*versions_cstr != NULL) { \
215 string versions_str = *versions_cstr; \
216 vector<SLBOSVersion> versions_arr = \
217 s_ParseVersionsString(versions_str); \
218 bool active = s_CheckTestVersion(versions_arr); \
219 if (!active) { \
220 WRITE_LOG("Test " << func_name << " is not active because " \
221 "LBOS has version \"" << \
222 s_LBOSVersion.major << "." << \
223 s_LBOSVersion.minor << "." << s_LBOSVersion.patch << \
224 "\" and test has version string \"" \
225 << versions_str << "\""); \
226 TEST_PASS; \
227 } \
228 } else { \
229 WRITE_LOG("Test " << func_name << " compatible LBOS versions not " \
230 "found in config. Allowing to run."); \
231 } \
232 } while (false)
233
234
235 /* LBOS returns 500 on announcement unexpectedly */
236 //#define QUICK_AND_DIRTY // define if announcements are repeated until success
237
238 /* We might want to clear ZooKeeper from nodes before running tests.
239 * This is generally not good, because if this test application runs
240 * on another host at the same moment, it will miss a lot of nodes and
241 * tests will fail.
242 */
243 #define DEANNOUNCE_ALL_BEFORE_TEST
244 /*test*/
245 #include "test_assert.h"
246
247
248 USING_NCBI_SCOPE;
249
250
251 /* Version of LBOS or this test */
252 struct SLBOSVersion
253 {
254 unsigned short major;
255 unsigned short minor;
256 unsigned short patch;
257
operator <SLBOSVersion258 bool operator<(const SLBOSVersion& rhs)
259 {
260 if (major != rhs.major)
261 return major < rhs.major;
262 if (minor != rhs.minor)
263 return minor < rhs.minor;
264 if (patch != rhs.patch)
265 return patch < rhs.patch;
266 return false;
267 }
operator ==SLBOSVersion268 bool operator==(const SLBOSVersion& rhs)
269 {
270 return major == rhs.major && minor == rhs.minor && patch == rhs.patch;
271 }
operator >SLBOSVersion272 bool operator>(const SLBOSVersion& rhs)
273 {
274 return !( *this < rhs || *this == rhs );
275 }
operator >=SLBOSVersion276 bool operator>=(const SLBOSVersion& rhs)
277 {
278 return (*this > rhs || *this == rhs);
279 }
operator <=SLBOSVersion280 bool operator<=(const SLBOSVersion& rhs)
281 {
282 return (*this < rhs || *this == rhs);
283 }
284 };
285
286 struct SLBOSResolutionError
287 {
288 int code_line;
289 int expected_count;
290 int count;
291 unsigned short port;
292 };
293
294
295 struct SServer
296 {
297 unsigned int host;
298 unsigned short port;
299 string version;
300 string service;
301 };
302
303
304 /* First let's declare some functions that will be
305 * used in different test suites. It is convenient
306 * that their definitions are at the very end, so that
307 * test config is as high as possible */
308 static CRef<CTls<int>> s_Tls(new CTls<int>);
309 static void s_PrintInfo (HOST_INFO);
310 static void s_TestFindMethod (ELBOSFindMethod);
311 static string s_PrintThreadNum ();
312 static void s_PrintAnnouncedServers ();
313
314 #ifdef NCBI_OS_MSWIN
315 static int s_GetTimeOfDay (struct timeval*);
316 #else
317 # define s_GetTimeOfDay(tv) gettimeofday(tv, 0)
318 #endif
319 static unsigned short s_Msb (unsigned short);
320 static const char* s_OS (TNcbiOSType);
321 static const char* s_Bits (TNcbiCapacity);
322 /** Count difference between two timestamps, in seconds*/
323 static double s_TimeDiff (const struct timeval*,
324 const struct timeval*);
325 static string s_GenerateNodeName (void);
326 static unsigned short s_GeneratePort ();
327 static bool s_CheckIfAnnounced (const string& service,
328 const string& version,
329 unsigned short server_port,
330 const string& health_suffix,
331 bool expectedAnnounced
332 = true,
333 string host = "");
334 static string s_ReadLBOSVersion (void);
335 static bool s_CheckTestVersion (vector<SLBOSVersion>
336 versions_arr);
337 static
338 vector<SLBOSVersion> s_ParseVersionsString (const string& versions);
339 static void s_PrintPortsLines (void);
340 static void s_PrintResolutionErrors (void);
341 static void s_Print500sCount (void);
342 static vector<SServer> s_GetAnnouncedServers (bool is_enabled = false,
343 vector<string> to_find
344 = vector<string>());
345
346 const int kThreadsNum = 34;
347 /** When the test is run in single-threaded mode, we set the number of the
348 * main thread to -1 to distinguish between MT and ST */
349 const int kSingleThreadNumber = -1;
350 const int kMainThreadNumber = 99;
351 const int kHealthThreadNumber = 100;
352 /* Seconds to try to find server. We wait maximum of 60 seconds. */
353 const int kDiscoveryDelaySec = 15;
354 /* for tests where port is not necessary (they fail before announcement) */
355 const unsigned short kDefaultPort = 5000;
356 /** Static variables that are used in mock functions.
357 * This is not thread-safe! */
358 static int s_CallCounter = 0;
359 /** It is yet impossible on TeamCity, but useful for local tests, where
360 * local LBOS can be easily run */
361 static string s_LastHeader;
362 static SLBOSVersion s_LBOSVersion = {0,0,0};
363 /** To remember on which line of code which port was announced
364 * (for debugging purposes) */
365 static map<int, int> s_PortsLines;
366 /* To remember on which line of code we did not find as many servers as
367 * expected */
368 static vector<SLBOSResolutionError> s_ResolutionErrors;
369 /** Remember how many times we got 500 */
370 static unsigned int s_500sCount = 0;
371
372
373 /* Mutex for thread-unsafe Boost checks */
374 DEFINE_STATIC_FAST_MUTEX(s_BoostTestLock);
375 /* Mutex for log output */
376 DEFINE_STATIC_FAST_MUTEX(s_WriteLogLock);
377
378 #define PORT_N 5 /* port for healthcheck */
379 #define PORT_STR_HELPER(port) #port
380 #define PORT_STR(port) PORT_STR_HELPER(port)
381
382 #ifdef NCBI_OS_MSWIN
383 # define LBOSRESOLVER_PATH "C:\\Apps\\Admin_Installs\\etc\\ncbi\\lbosresolver"
384 #elif defined NCBI_OS_LINUX
385 # define LBOSRESOLVER_PATH "/etc/ncbi/lbosresolver"
386 #endif
387
388 /*#define ANNOUNCEMENT_HOST string("iebdev22") */
389 #define ANNOUNCEMENT_HOST s_GetMyIP() /* The host which is used for healthchecks
390 in all test cases. By default,
391 ANNOUNCEMENT_HOST is set to s_GetMyIP()
392 For additional
393 tests it can be changed to any host */
394
395 /*#define ANNOUNCEMENT_HOST_0000 "iebdev22"*/
396 #define ANNOUNCEMENT_HOST_0000 "0.0.0.0"
397 /* The host which is used as 0.0.0.0.
398 For additional tests it can be
399 changed to some other host
400 address. */
401 const int kPortsNeeded = 9;
402 static CSafeStatic<vector<unsigned short>> s_ListeningPorts;
403
404 #include "test_ncbi_lbos_mocks.hpp"
405
406 #define WRITE_LOG(text) \
407 {{ \
408 CFastMutexGuard spawn_guard(s_WriteLogLock); \
409 LOG_POST(s_PrintThreadNum() << "\t" << __FILE__ << \
410 "\t" << __LINE__ << \
411 "\t" << text); \
412 }}
413
414 /* Trash collector for Thread Local Storage that stores thread number */
TlsCleanup(int * p_value,void *)415 void TlsCleanup(int* p_value, void* /* data */)
416 {
417 delete p_value;
418 }
419
s_PrintAnnouncementDetails(const char * name,const char * version,const char * host,const char * port,const char * health,const char * meta)420 static void s_PrintAnnouncementDetails(const char* name,
421 const char* version,
422 const char* host,
423 const char* port,
424 const char* health,
425 const char* meta)
426 {
427 WRITE_LOG("Announcing server \"" << (name ? name : "<NULL>") << "\"" <<
428 "with version " << (version ? version : "<NULL>") <<
429 ", port " << port <<
430 ", host " << host <<
431 ", healthcheck \"" << (health ? health : "<NULL>") << "\"" <<
432 ", meta \"" << (meta ? meta : "<NULL>") << "\"");
433 }
434
435
s_PrintAnnouncementDetails(const char * name,const char * version,const char * host,unsigned short port,const char * health,const char * meta)436 static void s_PrintAnnouncementDetails(const char* name,
437 const char* version,
438 const char* host,
439 unsigned short port,
440 const char* health,
441 const char* meta)
442 {
443 stringstream port_ss;
444 port_ss << port;
445 s_PrintAnnouncementDetails(name, version, host, port_ss.str().c_str(),
446 health, meta);
447 }
448
449
s_PrintAnnouncedDetails(const char * name,const char * version,const char * host,const char * port,const char * health,const char * meta,const char * lbos_ans,const char * lbos_mes,unsigned short result,double time_elapsed)450 static void s_PrintAnnouncedDetails(const char* name,
451 const char* version,
452 const char* host,
453 const char* port,
454 const char* health,
455 const char* meta,
456 const char* lbos_ans,
457 const char* lbos_mes,
458 unsigned short result,
459 double time_elapsed)
460 {
461 const char* message = lbos_mes ? lbos_mes : "<NULL>";
462 const char* status = lbos_ans ? lbos_ans : "<NULL>";
463 WRITE_LOG("Announcing server \"" << (name ? name : "<NULL>") << "\" " <<
464 "with version " << (version ? version : "<NULL>") <<
465 ", port " << port <<
466 ", host \"" << (host ? host : "<NULL>") <<
467 ", healthcheck \"" << (health ? health : "<NULL>") <<
468 ", meta \"" << (meta ? meta : "<NULL>") <<
469 " returned code " << result <<
470 " after " << time_elapsed << " seconds, " <<
471 ", status message: \"" << status << "\"" <<
472 ", body: \"" << message << "\"");
473 }
474
475
s_PrintAnnouncedDetails(const char * name,const char * version,const char * host,unsigned short port,const char * health,const char * meta,const char * lbos_ans,const char * lbos_mes,unsigned short result,double time_elapsed)476 static void s_PrintAnnouncedDetails(const char* name,
477 const char* version,
478 const char* host,
479 unsigned short port,
480 const char* health,
481 const char* meta,
482 const char* lbos_ans,
483 const char* lbos_mes,
484 unsigned short result,
485 double time_elapsed)
486 {
487 stringstream port_ss;
488 port_ss << port;
489 s_PrintAnnouncedDetails(name, version, host, port_ss.str().c_str(), health,
490 meta, lbos_ans, lbos_mes, result, time_elapsed);
491 }
492
s_GetRegistryAnnouncementParams(const char * registry_section,char ** srvc,char ** vers,char ** host,char ** port,char ** hlth,char ** meta)493 static void s_GetRegistryAnnouncementParams(const char* registry_section,
494 char** srvc,
495 char** vers,
496 char** host,
497 char** port,
498 char** hlth,
499 char** meta)
500 {
501 const char* kLBOSAnnouncementSection = "LBOS_ANNOUNCEMENT";
502 const char* kLBOSServiceVariable = "SERVICE";
503 const char* kLBOSVersionVariable = "VERSION";
504 const char* kLBOSHostVariable = "HOST";
505 const char* kLBOSPortVariable = "PORT";
506 const char* kLBOSHealthcheckUrlVariable = "HEALTHCHECK";
507 const char* kLBOSMetaVariable = "META";
508 if (g_LBOS_StringIsNullOrEmpty(registry_section)) {
509 registry_section = kLBOSAnnouncementSection;
510 }
511 *srvc = g_LBOS_RegGet(registry_section,
512 kLBOSServiceVariable,
513 NULL);
514 *vers = g_LBOS_RegGet(registry_section,
515 kLBOSVersionVariable,
516 NULL);
517 *host = g_LBOS_RegGet(registry_section,
518 kLBOSHostVariable,
519 NULL);
520 *port = g_LBOS_RegGet(registry_section,
521 kLBOSPortVariable,
522 NULL);
523 *hlth = g_LBOS_RegGet(registry_section,
524 kLBOSHealthcheckUrlVariable,
525 NULL);
526 *meta = g_LBOS_RegGet(registry_section,
527 kLBOSMetaVariable,
528 NULL);
529 }
530
531
s_PrintRegistryAnnouncementDetails(const char * registry_section)532 static void s_PrintRegistryAnnouncementDetails(const char* registry_section)
533 {
534 char* srvc_str, *vers_str, *host_str, *port_str, *hlth_str, *meta_str;
535 s_GetRegistryAnnouncementParams(registry_section, &srvc_str, &vers_str,
536 &host_str, &port_str, &hlth_str, &meta_str);
537 CCObjHolder<char> srvc(srvc_str);
538 CCObjHolder<char> vers(vers_str);
539 CCObjHolder<char> host(host_str);
540 CCObjHolder<char> port(port_str);
541 CCObjHolder<char> hlth(hlth_str);
542 CCObjHolder<char> meta(meta_str);
543 s_PrintAnnouncementDetails(srvc.Get(), vers.Get(), host.Get(), port.Get(),
544 hlth.Get(), meta.Get());
545 }
546
547
s_PrintRegistryAnnouncedDetails(const char * registry_section,const char * lbos_ans,const char * lbos_mes,unsigned short result,double time_elapsed)548 static void s_PrintRegistryAnnouncedDetails(const char* registry_section,
549 const char* lbos_ans,
550 const char* lbos_mes,
551 unsigned short result,
552 double time_elapsed)
553 {
554 char *srvc_str, *vers_str, *host_str, *port_str, *hlth_str, *meta_str;
555 s_GetRegistryAnnouncementParams(registry_section, &srvc_str, &vers_str,
556 &host_str, &port_str, &hlth_str, &meta_str);
557 CCObjHolder<char> srvc(srvc_str),
558 vers(vers_str),
559 host(host_str),
560 port(port_str),
561 hlth(hlth_str),
562 meta(meta_str);
563 s_PrintAnnouncedDetails(srvc.Get(), vers.Get(), host.Get(), port.Get(),
564 hlth.Get(), meta.Get(), lbos_ans, lbos_mes, result,
565 time_elapsed);
566 }
567
568
569 #define MEASURE_TIME_START \
570 struct timeval time_start; /**< to measure start of \
571 announcement */ \
572 struct timeval time_stop; /**< To check time at \
573 the end of each \
574 iteration*/ \
575 double time_elapsed = 0.0; /**< difference between start \
576 and end time */ \
577 if (s_GetTimeOfDay(&time_start) != 0) { /** Initialize time of \
578 iteration start*/ \
579 memset(&time_start, 0, sizeof(time_start)); \
580 }
581
582
583 #define MEASURE_TIME_FINISH \
584 if (s_GetTimeOfDay(&time_stop) != 0) \
585 memset(&time_stop, 0, sizeof(time_stop)); \
586 time_elapsed = s_TimeDiff(&time_stop, &time_start);
587
588
589 /** Announce using C interface. */
s_AnnounceC(const char * name,const char * version,const char * host,unsigned short port,const char * health,const char * meta,char ** lbos_ans,char ** lbos_mes,bool safe=false)590 static unsigned short s_AnnounceC(const char* name,
591 const char* version,
592 const char* host,
593 unsigned short port,
594 const char* health,
595 const char* meta,
596 char** lbos_ans,
597 char** lbos_mes,
598 bool safe = false)
599 {
600 unsigned short result;
601 MEASURE_TIME_START;
602 const char * healthcheck_cstr = NULL; //NULL if health is NULL
603 string healthcheck_str; //for c_str() to retain value until end of function
604 if (health != NULL) {
605 stringstream healthcheck;
606 healthcheck << health << "/port" << port <<
607 "/host" << (host ? host : "") <<
608 "/version" << (version ? version : "");
609 ;
610 healthcheck_cstr = (healthcheck_str = healthcheck.str()).c_str();
611 }
612
613 s_PrintAnnouncementDetails(name, version, host, port,
614 healthcheck_cstr, meta);
615
616 if (safe) {
617 /* If announcement finishes with error - return
618 * error */
619 result = LBOS_Announce(name, version, host, port, healthcheck_cstr,
620 meta, lbos_ans, lbos_mes);
621 } else {
622 /* If announcement finishes with error - try again
623 * until success (with invalid parameters means infinite loop) */
624 result = s_LBOS_Announce(name, version, host, port, healthcheck_cstr,
625 meta, lbos_ans, lbos_mes);
626 }
627 MEASURE_TIME_FINISH;
628 if (result == 500) {
629 s_500sCount++;
630 }
631 s_PrintAnnouncedDetails(name, version, host, port,
632 healthcheck_cstr, meta,
633 lbos_ans ? *lbos_ans : NULL,
634 lbos_mes ? *lbos_mes : NULL,
635 result, time_elapsed);
636 return result;
637 }
638
639
s_AnnounceC(const string & name,const string & version,const string & host,unsigned short port,const string & health,const string & meta,char ** lbos_ans,char ** lbos_mes,bool safe=false)640 static unsigned short s_AnnounceC(const string& name,
641 const string& version,
642 const string& host,
643 unsigned short port,
644 const string& health,
645 const string& meta,
646 char** lbos_ans,
647 char** lbos_mes,
648 bool safe = false)
649 {
650 return s_AnnounceC(name.c_str(), version.c_str(), host.c_str(),
651 port, health.c_str(), meta.c_str(), lbos_ans,
652 lbos_mes, safe);
653 }
654
655
s_AnnounceCSafe(const char * name,const char * version,const char * host,unsigned short port,const char * health,const char * meta,char ** lbos_ans,char ** lbos_mes)656 static unsigned short s_AnnounceCSafe(const char* name,
657 const char* version,
658 const char* host,
659 unsigned short port,
660 const char* health,
661 const char* meta,
662 char** lbos_ans,
663 char** lbos_mes)
664 {
665 unsigned short result;
666 MEASURE_TIME_START;
667 const char * healthcheck_cstr = NULL; //NULL if health is NULL
668 string healthcheck_str; //for c_str() to retain value until end of function
669 if (health != NULL) {
670 stringstream healthcheck;
671 healthcheck << health << "/port" << port <<
672 "/host" << (host ? host : "") <<
673 "/version" << (version ? version : "");
674 ;
675 healthcheck_cstr = (healthcheck_str = healthcheck.str()).c_str();
676 }
677
678 s_PrintAnnouncementDetails(name, version, host, port,
679 healthcheck_cstr, meta);
680 result = s_LBOS_Announce(name, version, host, port, healthcheck_cstr,
681 meta, lbos_ans, lbos_mes);
682 MEASURE_TIME_FINISH;
683 s_PrintAnnouncedDetails(name, version, host, port,
684 healthcheck_cstr, meta,
685 lbos_ans ? *lbos_ans : NULL,
686 lbos_mes ? *lbos_mes : NULL,
687 result, time_elapsed);
688 return result;
689 }
690
691
s_AnnounceCSafe(const string & name,const string & version,const string & host,unsigned short port,const string & health,const string & meta,char ** lbos_ans,char ** lbos_mes)692 static unsigned short s_AnnounceCSafe(const string& name,
693 const string& version,
694 const string& host,
695 unsigned short port,
696 const string& health,
697 const string& meta,
698 char** lbos_ans,
699 char** lbos_mes)
700 {
701 return s_AnnounceCSafe(name.c_str(), version.c_str(), host.c_str(),
702 port, health.c_str(), meta.c_str(),
703 lbos_ans, lbos_mes);
704 }
705
706
707 /** Announce using C interface and using values from registry. If announcement
708 * finishes with error - try again until success (with invalid parameters means
709 * infinite loop) */
s_AnnounceCRegistry(const char * registry_section,char ** lbos_ans,char ** lbos_mes)710 static unsigned short s_AnnounceCRegistry(const char* registry_section,
711 char** lbos_ans,
712 char** lbos_mes)
713 {
714 unsigned short result;
715 s_PrintRegistryAnnouncementDetails(registry_section);
716 MEASURE_TIME_START
717 result = s_LBOS_AnnounceReg(registry_section, lbos_ans, lbos_mes);
718 MEASURE_TIME_FINISH
719 s_PrintRegistryAnnouncedDetails(registry_section,
720 lbos_ans ? *lbos_ans : NULL,
721 lbos_mes ? *lbos_mes : NULL,
722 result, time_elapsed);
723 return result;
724 }
725
726
727 /** Announce using C++ interface. If announcement finishes with error - return
728 * error */
s_AnnounceCPP(const string & name,const string & version,const string & host,unsigned short port,const string & health,const LBOS::CMetaData & meta=LBOS::CMetaData ())729 static void s_AnnounceCPP(const string& name,
730 const string& version,
731 const string& host,
732 unsigned short port,
733 const string& health,
734 const LBOS::CMetaData& meta = LBOS::CMetaData())
735 {
736 s_PrintAnnouncementDetails(name.c_str(), version.c_str(), host.c_str(),
737 port, health.c_str(),
738 meta.GetMetaString().c_str());
739 stringstream healthcheck;
740 healthcheck << health << "/port" << port << "/host" << host <<
741 "/version" << version;
742 MEASURE_TIME_START
743 try {
744 LBOS::Announce(name, version, host, port, healthcheck.str(), meta);
745 }
746 catch (CLBOSException& ex) {
747 MEASURE_TIME_FINISH
748 if (ex.GetErrCode() == 500) {
749 s_500sCount++;
750 }
751 s_PrintAnnouncedDetails(name.c_str(), version.c_str(),
752 host.c_str(), port, health.c_str(),
753 meta.GetMetaString().c_str(),
754 ex.what(), ex.GetErrCodeString(),
755 ex.GetErrCode(), time_elapsed);
756 throw; /* Move the exception down the stack */
757 }
758 MEASURE_TIME_FINISH
759 /* Print good result */
760 s_PrintAnnouncedDetails(name.c_str(), version.c_str(), host.c_str(), port,
761 health.c_str(), meta.GetMetaString().c_str(),
762 "<C++ does not show answer from LBOS on success>",
763 "OK", 200, time_elapsed);
764 }
765
766
767 /** Announce using C++ interface. If announcement finishes with error - try
768 * again until success (with invalid parameters means infinite loop) */
s_AnnounceCPPSafe(const string & name,const string & version,const string & host,unsigned short port,const string & health,const LBOS::CMetaData & meta=LBOS::CMetaData ())769 static void s_AnnounceCPPSafe(const string& name,
770 const string& version,
771 const string& host,
772 unsigned short port,
773 const string& health,
774 const LBOS::CMetaData& meta = LBOS::CMetaData())
775 {
776 s_PrintAnnouncementDetails(name.c_str(), version.c_str(), host.c_str(),
777 port, health.c_str(),
778 meta.GetMetaString().c_str());
779 stringstream healthcheck;
780 healthcheck << health << "/port" << port << "/host" << host <<
781 "/version" << version;
782 MEASURE_TIME_START
783 s_LBOS_CPP_Announce(name, version, host, port, healthcheck.str(), meta);
784 MEASURE_TIME_FINISH
785 /* Print good result */
786 s_PrintAnnouncedDetails(name.c_str(), version.c_str(), host.c_str(), port,
787 health.c_str(), meta.GetMetaString().c_str(),
788 "<C++ does not show answer from LBOS on success>",
789 "OK", 200, time_elapsed);
790 }
791
792
793 /** Announce using C++ interface and using values from registry. If
794 * announcement finishes with error - try again until success (with invalid
795 * parameters meaning infinite loop) */
s_AnnounceCPPFromRegistry(const string & registry_section)796 static void s_AnnounceCPPFromRegistry(const string& registry_section)
797 {
798 s_PrintRegistryAnnouncementDetails(registry_section.c_str());
799 MEASURE_TIME_START
800 try {
801 s_LBOS_CPP_AnnounceReg(registry_section);
802 } catch (CLBOSException& ex) {
803 MEASURE_TIME_FINISH
804 if (ex.GetErrCode() == 500) {
805 s_500sCount++;
806 }
807 s_PrintRegistryAnnouncedDetails(registry_section.c_str(), ex.what(),
808 ex.GetErrCodeString(),
809 ex.GetErrCode(), time_elapsed);
810 throw; /* Move the exception down the stack */
811 }
812 MEASURE_TIME_FINISH
813 /* Print good result */
814 s_PrintRegistryAnnouncedDetails(registry_section.c_str(),
815 "<C++ does not show answer from LBOS>",
816 "OK", 200, time_elapsed);
817 }
818
819
820 /** Before deannounce */
s_PrintDeannouncementDetails(const char * name,const char * version,const char * host,unsigned short port)821 static void s_PrintDeannouncementDetails(const char* name,
822 const char* version,
823 const char* host,
824 unsigned short port)
825 {
826 WRITE_LOG("De-announcing server \"" <<
827 (name ? name : "<NULL>") <<
828 "\" with version " << (version ? version : "<NULL>") <<
829 ", port " << port << ", host \"" <<
830 (host ? host : "<NULL>") << "\", ip " << s_GetMyIP());
831 }
832
833 /** Before deannounce */
s_PrintDeannouncedDetails(const char * name,const char * version,const char * host,unsigned short port,const char * lbos_ans,const char * lbos_mess,unsigned short result,double time_elapsed)834 static void s_PrintDeannouncedDetails(const char* name,
835 const char* version,
836 const char* host,
837 unsigned short port,
838 const char* lbos_ans,
839 const char* lbos_mess,
840 unsigned short result,
841 double time_elapsed)
842 {
843 WRITE_LOG("De-announce of server \"" <<
844 (name ? name : "<NULL>") <<
845 "\" with version " << (version ? version : "<NULL>") <<
846 ", port " << port << ", host \"" <<
847 (host ? host : "<NULL>") << " returned code " << result <<
848 " after " << time_elapsed << " seconds, "
849 ", LBOS status message: \"" <<
850 (lbos_mess ? lbos_mess : "<NULL>") <<
851 "\", LBOS answer: \"" <<
852 (lbos_ans ? lbos_ans : "<NULL>") << "\"");
853 }
854
s_DeannounceC(const char * name,const char * version,const char * host,unsigned short port,char ** lbos_ans,char ** lbos_mes)855 static unsigned short s_DeannounceC(const char* name,
856 const char* version,
857 const char* host,
858 unsigned short port,
859 char** lbos_ans,
860 char** lbos_mes)
861 {
862 unsigned short result;
863 s_PrintDeannouncementDetails(name, version, host, port);
864 MEASURE_TIME_START
865 result = LBOS_Deannounce(name, version, host, port, lbos_ans, lbos_mes);
866 MEASURE_TIME_FINISH
867 if (result == 500) {
868 s_500sCount++;
869 }
870 s_PrintDeannouncedDetails(name, version, host, port,
871 lbos_ans ? *lbos_ans : NULL,
872 lbos_mes ? *lbos_mes : NULL,
873 result, time_elapsed);
874 return result;
875 }
876
s_DeannounceAll()877 static void s_DeannounceAll()
878 {
879 WRITE_LOG("De-announce all");
880 MEASURE_TIME_START;
881 LBOS_DeannounceAll();
882 MEASURE_TIME_FINISH;
883 WRITE_LOG("De-announce all has finished and took " <<
884 time_elapsed << " seconds.");
885 }
886
s_DeannounceCPP(const string & name,const string & version,const string & host,unsigned short port)887 static void s_DeannounceCPP(const string& name,
888 const string& version,
889 const string& host,
890 unsigned short port)
891 {
892 s_PrintDeannouncementDetails(name.c_str(), version.c_str(), host.c_str(),
893 port);
894 MEASURE_TIME_START
895 try {
896 LBOS::Deannounce(name, version, host, port);
897 }
898 catch (CLBOSException& ex) {
899 MEASURE_TIME_FINISH
900 if (ex.GetStatusCode() == 500) {
901 s_500sCount++;
902 }
903 s_PrintDeannouncedDetails(name.c_str(), version.c_str(),
904 host.c_str(), port,
905 ex.what(), ex.GetErrCodeString(),
906 ex.GetStatusCode(), time_elapsed);
907 throw; /* Move the exception down the stack */
908 }
909 MEASURE_TIME_FINISH
910 /* Print good result */
911 s_PrintDeannouncedDetails(name.c_str(), version.c_str(), host.c_str(),
912 port, "<C++ does not show answer from LBOS>",
913 "OK", 200, time_elapsed);
914 }
915
916 // Macro, because we want to know from which line this was called
917 // (original line will be shown in WRITE_LOG)
918 #define SELECT_PORT(count_before,node_name,port) \
919 do { \
920 port = s_GeneratePort(); \
921 count_before = s_CountServers(node_name, port); \
922 while (count_before != 0) { \
923 port = s_GeneratePort(); \
924 count_before = s_CountServers(node_name, port); \
925 } \
926 WRITE_LOG("Random port is " << port << ". " \
927 "Count of servers with this port is " << \
928 count_before << "."); \
929 s_PortsLines[port] = __LINE__; \
930 } while (false)
931
932
933 /** Print all ports with which servers were announced, and line of code which
934 * initiated each announcement */
s_PrintPortsLines()935 static void s_PrintPortsLines()
936 {
937 /* We will not surround it with mutex because it is not so important */
938 static bool already_launched = false;
939 if (already_launched) return;
940 already_launched = true;
941
942 stringstream ports_lines;
943 ports_lines << "Printing port<->line:" << endl;
944 auto ports_iter = s_PortsLines.begin();
945 for ( ; ports_iter != s_PortsLines.end() ; ports_iter++ ) {
946 ports_lines << "Port " << ports_iter->first
947 << " was announced on line " << ports_iter->second << endl;
948 }
949 WRITE_LOG(ports_lines.str());
950 }
951
952
953 /** Print all cases when we did not find as many servers as expected. Write
954 * line of code which started counting, port of server searched, expected count
955 * and real count */
s_PrintResolutionErrors()956 static void s_PrintResolutionErrors()
957 {
958 /* We will not surround it with mutex because it is not so important */
959 static bool already_launched = false;
960 if (already_launched) return;
961 already_launched = true;
962
963 stringstream errors;
964 errors << "Printing s_CountServersWithExpectation errors:" << endl;
965 auto errors_iter = s_ResolutionErrors.begin();
966 for (; errors_iter != s_ResolutionErrors.end(); errors_iter++) {
967 errors << "Port " << errors_iter->port << " "
968 << "was announced on line " << errors_iter->code_line << ", "
969 << "expected to find " << errors_iter->expected_count << ", "
970 << "but " << errors_iter->count << " was found instead"
971 << endl;
972 }
973 WRITE_LOG(errors.str());
974 }
975
976
s_Print500sCount()977 static void s_Print500sCount()
978 {
979 WRITE_LOG("Got " << s_500sCount << " 500's during test");
980 }
981
982
s_FindAnnouncedServer(const string & service,const string & version,unsigned short port,const string & host)983 static int s_FindAnnouncedServer(const string& service,
984 const string& version,
985 unsigned short port,
986 const string& host)
987 {
988 WRITE_LOG("Trying to find announced server in the storage\"" <<
989 service << "\" with version " << version << ", port " <<
990 port << ", ip " << host);
991
992
993 CLBOSStatus lbos_status(true, true);
994 struct SLBOS_AnnounceHandle_Tag*& arr =
995 *g_LBOS_UnitTesting_GetAnnouncedServers();
996 CORE_LOCK_READ;
997 unsigned int count = g_LBOS_UnitTesting_GetAnnouncedServersNum();
998 unsigned int found = 0;
999 /* Just iterate and compare */
1000 unsigned int i = 0;
1001 for (i = 0; i < count; i++) {
1002 if (strcasecmp(service.c_str(), arr[i].service) == 0
1003 &&
1004 strcasecmp(version.c_str(), arr[i].version) == 0
1005 &&
1006 strcasecmp(host.c_str(), arr[i].host) == 0
1007 &&
1008 port == arr[i].port)
1009 {
1010 WRITE_LOG("Found a server of \"" <<
1011 arr[i].service << "\" with version " << arr[i].version <<
1012 ", port " << arr[i].port << ", ip " << arr[i].host
1013 << ", #" << i);
1014 found++;
1015 break;
1016 }
1017 }
1018 CORE_UNLOCK;
1019 WRITE_LOG("Found " << found << " servers in the inner LBOS storage");
1020 if (found > 1) {
1021 s_PrintAnnouncedServers();
1022 }
1023 return found;
1024 }
1025
1026 /** To run tests of /configuration we need name of service that is not used yet.
1027 */
s_CheckServiceKnown(const string & service)1028 static bool s_CheckServiceKnown(const string& service)
1029 {
1030 bool exists;
1031 LBOSPrivate::GetServiceVersion(service, &exists);
1032 return exists;
1033 }
1034
1035 /** Special service name for /configure endpoint tests. Telle that it is
1036 * safe to delete it and is unique for each host that create them */
s_GetUnknownService()1037 static string s_GetUnknownService() {
1038 static string charset = "abcdefghijklmnopqrstuvwxyz"
1039 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1040 "1234567890";
1041 const int length = 10;
1042 unsigned int i;
1043 for (;;) {
1044 string result =
1045 string("/deleteme") + NStr::Replace(s_GetMyIP(),".", "");
1046 i = result.length();
1047 result.resize(result.length() + length);
1048 for ( ; i < result.length(); i++) {
1049 result[i] = charset[rand() % charset.length()];
1050 }
1051 if (!s_CheckServiceKnown(result)) {
1052 return result;
1053 }
1054 }
1055 return ""; /* never reachable */
1056 }
1057
s_CleanDTabs()1058 static void s_CleanDTabs() {
1059 vector<string> nodes_to_delete;
1060 CConnNetInfo net_info;
1061 size_t start = 0,
1062 end = 0;
1063 CCObjHolder<char> lbos_address (g_LBOS_GetLBOSAddress());
1064 string lbos_addr (lbos_address.Get());
1065 CCObjHolder<char> lbos_output_orig(g_LBOS_UnitTesting_GetLBOSFuncs()->
1066 UrlReadAll(*net_info,
1067 (string("http://") + lbos_addr +
1068 "/admin/dtab").c_str(), NULL, NULL));
1069 if (*lbos_output_orig == NULL)
1070 lbos_output_orig = strdup("");
1071 string lbos_output = *lbos_output_orig;
1072 WRITE_LOG("admin/dtab output: \n" << lbos_output);
1073 string to_find = string("/deleteme") + NStr::Replace(s_GetMyIP(),".", "");
1074 while (start != string::npos) {
1075 start = lbos_output.find(to_find, start);
1076 if (start == string::npos)
1077 break;
1078 // We already know service name since we searched for it.
1079 end = lbos_output.find("=>", start); //skip service name
1080 string service = lbos_output.substr(start, end - start);
1081 service = NStr::Replace(service, " ", "");
1082 nodes_to_delete.push_back(service);
1083 start = lbos_output.find("\n", end + 1); //skip "=>/zk#/"
1084 }
1085
1086 vector<string>::iterator it;
1087 for (it = nodes_to_delete.begin(); it != nodes_to_delete.end(); it++ ) {
1088 LBOSPrivate::DeleteServiceVersion(*it);
1089 }
1090 }
1091
s_PortStr(unsigned int i=0)1092 static string s_PortStr(unsigned int i = 0)
1093 {
1094 if (i >= s_ListeningPorts->size()) {
1095 WRITE_LOG("Error index in s_PortStr(): " << i);
1096 i = 0;
1097 }
1098 return NStr::IntToString((*s_ListeningPorts)[i]);
1099 }
1100
1101
1102 /* We know that the server was announced and just have to wait for it to appear
1103 * in LBOS output */
s_WaitTillAnnounced(string service,const SConnNetInfo * net_info,const char * arg,const char * val)1104 static void s_WaitTillAnnounced(
1105 string service, /* service name (here: can be a mask!) */
1106 const SConnNetInfo* net_info,
1107 const char* arg,
1108 const char* val)
1109 {
1110 int retries = 0, max_retries = 10;
1111 CServIter res;
1112 int wait_msec = 500;
1113
1114 do {
1115 if (retries++)
1116 SleepMilliSec(wait_msec);
1117 WRITE_LOG("Running s_WaitTillAnnounced with "
1118 "\"service\": \"" << service << "\", "
1119 "\"arg\": " << (arg ? arg : "<NULL>") << "\", "
1120 "\"val\": " << (val ? val : "<NULL>") << "\", "
1121 "retry #" << retries+1);
1122 res = SERV_OpenP(service.c_str(), fSERV_All, SERV_LOCALHOST, 0, 0.0,
1123 net_info, 0, 0, 0, arg, val);
1124 } while (*res == NULL && retries < max_retries);
1125 WRITE_LOG("s_WaitTillAnnounced with "
1126 "\"service\": \"" << service << "\", "
1127 << (*res ? "" : "NOT ") << "found announced servers after "
1128 << retries+1 << " retries");
1129 }
1130
s_SERVOpenP_Safe(const char * service,TSERV_Type types,unsigned int preferred_host,unsigned short preferred_port,double preference,const SConnNetInfo * net_info,SSERV_InfoCPtr skip[],size_t n_skip,int external,const char * arg,const char * val,int expected_count=1)1131 static SERV_ITER s_SERVOpenP_Safe(
1132 const char* service, /* service name (here: can be a mask!) */
1133 TSERV_Type types,
1134 unsigned int preferred_host,
1135 unsigned short preferred_port,
1136 double preference,
1137 const SConnNetInfo* net_info,
1138 SSERV_InfoCPtr skip[], /* must be "named" if service is a mask!*/
1139 size_t n_skip,
1140 int/*bool*/ external,
1141 const char* arg,
1142 const char* val,
1143 int expected_count = 1)
1144 {
1145 int retries = 0, max_retries = 10;
1146 SERV_ITER res = NULL;
1147 int wait_msec = 500;
1148
1149 do {
1150 if (retries++)
1151 SleepMilliSec(wait_msec);
1152 WRITE_LOG("Running SERV_OpenP with "
1153 "\"service\": \"" << (service ? service : "<NULL>") << "\", "
1154 "\"types\": " << types << ", "
1155 "preferred host and port: " <<
1156 CSocketAPI::HostPortToString(preferred_host,
1157 preferred_port) << ", "
1158 "\"arg\": " << (arg ? arg : "<NULL>") << "\", "
1159 "\"val\": " << (val ? val : "<NULL>") << "\", "
1160 "retry #" << retries+1);
1161 res = SERV_OpenP(service, types, preferred_host, preferred_port,
1162 preference, net_info, skip, n_skip, external,
1163 arg, val);
1164 } while ((expected_count ? res == NULL : res != NULL) &&
1165 retries < max_retries);
1166 WRITE_LOG("SERV_OpenP with "
1167 "\"service\": \"" << (service ? service : "<NULL>") << "\", "
1168 "\"types\": " << types << ", "
1169 "preferred host and port: " <<
1170 CSocketAPI::HostPortToString(preferred_host,
1171 preferred_port) << ", "
1172 << (res ? "" : "NOT ") << "found announced servers after "
1173 << retries+1 << " retries");
1174 return res;
1175 }
1176 class CHealthcheckThread
1177 #ifdef NCBI_THREADS
1178 : public CThread
1179 #endif /* NCBI_THREADS */
1180 {
1181 public:
CHealthcheckThread()1182 CHealthcheckThread()
1183 : m_RunHealthCheck(true)
1184 {
1185 m_Busy = false;
1186 for (unsigned short port = 8080; port < 8110; port++) {
1187 if ( m_ListeningSockets.size() >= kPortsNeeded ) break;
1188 CListeningSocket* l_sock = new CListeningSocket(port);
1189 if (l_sock->GetStatus() == eIO_Success) {
1190 s_ListeningPorts->push_back(port);
1191 m_ListeningSockets.push_back(CSocketAPI::SPoll(l_sock,
1192 eIO_ReadWrite));
1193 } else {
1194 l_sock->Close();
1195 delete l_sock;
1196 }
1197 }
1198 if (s_ListeningPorts->size() < kPortsNeeded) {
1199 throw CLBOSException(CDiagCompileInfo(), NULL,
1200 CLBOSException::eUnknown,
1201 "Not enough vacant ports to start listening",
1202 0);
1203 }
1204 }
Stop()1205 void Stop()
1206 {
1207 m_RunHealthCheck = false;
1208 }
1209 /* Check if thread has answered all requests */
IsBusy()1210 bool IsBusy()
1211 {
1212 return m_Busy;
1213 }
1214
AnswerHealthcheck()1215 void AnswerHealthcheck()
1216 {
1217 WRITE_LOG("AnswerHealthcheck() started, m_ListeningSockets has "
1218 << s_ListeningPorts->size() << " open listening sockets"
1219 << " and " << m_SocketPool.size() << " open connections");
1220 /* Keeping number of open sockets under control at all times! */
1221 int collect_grbg_retries = 0;
1222 while ((m_SocketPool.size() > 150) && (++collect_grbg_retries < 10))
1223 CollectGarbage();
1224 struct timeval accept_time_stop;
1225 STimeout rw_timeout = { 1, 20000 };
1226 STimeout accept_timeout = { 0, 20000 };
1227 STimeout c_timeout = { 0, 0 };
1228 int iters_passed = 0;
1229 size_t n_ready = 0;
1230 int secs_btw_grbg_cllct = 5;/* collect garbage every 5s */
1231 int iters_btw_grbg_cllct = secs_btw_grbg_cllct * 100000 /
1232 (rw_timeout.sec * 100000 +
1233 rw_timeout.usec);
1234
1235 if (s_GetTimeOfDay(&accept_time_stop) != 0) {
1236 memset(&accept_time_stop, 0, sizeof(accept_time_stop));
1237 }
1238 auto it = m_ListeningSockets.begin();
1239 CSocketAPI::Poll(m_ListeningSockets, &rw_timeout, &n_ready);
1240 for (; it != m_ListeningSockets.end(); it++) {
1241 if (it->m_REvent != eIO_Open && it->m_REvent != eIO_Close) {
1242 CSocket* sock = new CSocket;
1243 struct timeval accept_time_start;
1244 struct timeval accept_time_stop;
1245 if (s_GetTimeOfDay(&accept_time_start) != 0) {
1246 memset(&accept_time_start, 0, sizeof(accept_time_start));
1247 }
1248 double accept_time_elapsed = 0.0;
1249 double last_accept_time_elapsed = 0.0;
1250 if (static_cast<CListeningSocket*>(it->m_Pollable)->
1251 Accept(*sock, &accept_timeout) != eIO_Success)
1252 {
1253 if (s_GetTimeOfDay(&accept_time_stop) != 0)
1254 memset(&accept_time_stop, 0, sizeof(accept_time_stop));
1255 accept_time_elapsed = s_TimeDiff(&accept_time_stop,
1256 &accept_time_start);
1257 last_accept_time_elapsed = s_TimeDiff(&accept_time_stop,
1258 &m_LastSuccAcceptTime);
1259 WRITE_LOG("healthcheck vacant after trying accept for "
1260 << accept_time_elapsed << "s, last successful "
1261 "accept was " << last_accept_time_elapsed
1262 << "s ago");
1263 m_Busy = false;
1264 delete sock;
1265 return;
1266 }
1267
1268 if (s_GetTimeOfDay(&accept_time_stop) != 0)
1269 memset(&accept_time_stop, 0, sizeof(accept_time_stop));
1270 accept_time_elapsed =
1271 s_TimeDiff(&accept_time_stop, &accept_time_start);
1272 last_accept_time_elapsed =
1273 s_TimeDiff(&accept_time_stop, &m_LastSuccAcceptTime);
1274 if (s_GetTimeOfDay(&m_LastSuccAcceptTime) != 0) {
1275 memset(&m_LastSuccAcceptTime, 0,
1276 sizeof(m_LastSuccAcceptTime));
1277 }
1278
1279 CSocket* my_sock;
1280 m_SocketPool.push_back(
1281 CSocketAPI::SPoll(my_sock = sock, eIO_ReadWrite));
1282 iters_passed++;
1283 m_Busy = true;
1284 char buf[4096];
1285 size_t n_read = 0;
1286 size_t n_written = 0;
1287 my_sock->SetTimeout(eIO_ReadWrite, &rw_timeout);
1288 my_sock->SetTimeout(eIO_Close, &c_timeout);
1289 my_sock->Read(buf, sizeof(buf), &n_read);
1290 buf[n_read] = '\0';
1291 string request = buf;
1292 if (request.length() > 10) {
1293 request = request.substr(4, NPOS);
1294 request = request.erase(request.find("HTTP"), NPOS);
1295 WRITE_LOG("Answered healthcheck for " << request <<
1296 " after trying accept for "
1297 << accept_time_elapsed
1298 << "s, last successful accept was "
1299 << last_accept_time_elapsed << "s ago");
1300 }
1301 if (request == "/health" || request == "") {
1302 WRITE_LOG("Answered healthcheck for " << request <<
1303 " after trying accept for "
1304 << accept_time_elapsed
1305 << "s, last successful accept was "
1306 << last_accept_time_elapsed << "s ago");
1307 }
1308 const char healthy_answer[] =
1309 "HTTP/1.1 200 OK\r\n"
1310 "Content-Length: 4\r\n"
1311 "Content-Type: text/plain;charset=UTF-8\r\n"
1312 "\r\n"
1313 "OK\r\n";
1314 my_sock->Write(healthy_answer, sizeof(healthy_answer) - 1,
1315 &n_written);
1316
1317 if (iters_passed == iters_btw_grbg_cllct) {
1318 iters_passed = 0;
1319 CollectGarbage();
1320 }
1321 }
1322 }
1323 }
1324
1325
1326 protected:
1327 // As it is said in ncbithr.hpp, destructor must be protected
~CHealthcheckThread()1328 ~CHealthcheckThread()
1329 {
1330 WRITE_LOG("~CHealthcheckThread() started");
1331 for (unsigned int i = 0; i < m_ListeningSockets.size(); ++i) {
1332 CListeningSocket* l_sock = static_cast<CListeningSocket*>
1333 (m_ListeningSockets[i].m_Pollable);
1334 l_sock->Close();
1335 delete l_sock;
1336 }
1337 for (unsigned int i = 0; i < 100 /* random number */; ++i) {
1338 if (!HasGarbage()) break;
1339 CollectGarbage();
1340 SleepMilliSec(20);
1341 }
1342 m_ListeningSockets.clear();
1343 WRITE_LOG("~CHealthcheckThread() ended");
1344 }
1345
1346 private:
1347 /* Go through sockets in collection and remove closed ones */
CollectGarbage()1348 void CollectGarbage()
1349 {
1350 WRITE_LOG("CHealthcheckThread::CollectGarbage() started, size of "
1351 "m_SocketPool is " << m_SocketPool.size());
1352 size_t n_ready;
1353 STimeout rw_timeout = { 1, 20000 };
1354 /*
1355 * Divide polls in parts if there are more that 60 sockets
1356 */
1357 size_t polls_size = m_SocketPool.size(), chunk_size = 60, j = 0;
1358 // do we have more than one chunk?
1359 if (polls_size > chunk_size) {
1360 // handle all but the last chunk
1361 for (; j < polls_size - chunk_size; j += chunk_size) {
1362 vector<CSocketAPI::SPoll>::iterator begin, end;
1363 begin = m_SocketPool.begin() + j;
1364 end = m_SocketPool.begin() + j + chunk_size;
1365 vector<CSocketAPI::SPoll> polls(begin, end);
1366 CSocketAPI::Poll(polls, &rw_timeout, &n_ready);
1367 /* save result of poll */
1368 for (size_t k = 0; k < chunk_size; ++k) {
1369 m_SocketPool[j + k].m_REvent = polls[k].m_REvent;
1370 }
1371 }
1372 }
1373 // if we still have a part of a chunk left, handle it
1374 if (polls_size - j > 0) {
1375 auto begin = m_SocketPool.begin() + j;
1376 auto end = m_SocketPool.end();
1377 vector<CSocketAPI::SPoll> polls(begin, end);
1378 CSocketAPI::Poll(polls, &rw_timeout, &n_ready);
1379 for (size_t k = 0; k < polls_size - j; ++k) {
1380 m_SocketPool[j + k].m_REvent = polls[k].m_REvent;
1381 }
1382 }
1383
1384 /* We check sockets that have some events */
1385 unsigned int i;
1386
1387 WRITE_LOG("m_SocketPool has " << m_SocketPool.size() << " sockets");
1388 for (i = 0; i < m_SocketPool.size(); ++i) {
1389 if (m_SocketPool[i].m_REvent == eIO_ReadWrite) {
1390 /* If this socket has some event */
1391 CSocket* sock =
1392 static_cast<CSocket*>(m_SocketPool[i].m_Pollable);
1393 sock->Close();
1394 delete sock;
1395 /* Remove item from vector by swap and pop_back */
1396 swap(m_SocketPool[i], m_SocketPool.back());
1397 m_SocketPool.pop_back();
1398 }
1399 }
1400 WRITE_LOG("CHealthcheckThread::CollectGarbage() ended, size of "
1401 "m_SocketPool is " << m_SocketPool.size());
1402 }
1403
HasGarbage()1404 bool HasGarbage() {
1405 return m_SocketPool.size() > 0;
1406 }
1407
Main(void)1408 void* Main(void) {
1409 s_Tls->SetValue(new int, TlsCleanup);
1410 *s_Tls->GetValue() = kHealthThreadNumber;
1411 #ifdef NCBI_MONKEY
1412 CMonkey::Instance()->
1413 RegisterThread(kHealthThreadNumber);
1414 #endif /* NCBI_MONKEY */
1415 WRITE_LOG("Healthcheck thread started");
1416 if (s_GetTimeOfDay(&m_LastSuccAcceptTime) != 0) {
1417 memset(&m_LastSuccAcceptTime, 0, sizeof(m_LastSuccAcceptTime));
1418 }
1419 while (m_RunHealthCheck) {
1420 AnswerHealthcheck();
1421 }
1422 return NULL;
1423 }
1424 /** Pool of listening sockets */
1425 vector<CSocketAPI::SPoll> m_ListeningSockets;
1426 /** Pool of sockets created by accept() */
1427 vector<CSocketAPI::SPoll> m_SocketPool;
1428 /** time of last successful accept() */
1429 struct timeval m_LastSuccAcceptTime;
1430 bool m_RunHealthCheck;
1431 bool m_Busy;
1432 map<unsigned short, short> m_ListenPorts;
1433 };
1434
1435 static CHealthcheckThread* s_HealthcheckThread;
1436
1437
1438
1439 /** Check if expected number of specified servers is announced
1440 * (usually it is 0 or 1)
1441 * This function does not care about host (IP) of server.
1442 */
s_CountServersWithExpectation(const string & service,unsigned short port,int expected_count,size_t code_line,int secs_timeout,const string & dtab="")1443 int s_CountServersWithExpectation(const string& service,
1444 unsigned short port,
1445 int expected_count,
1446 size_t code_line,
1447 int secs_timeout,
1448 const string& dtab = "")
1449 {
1450 CConnNetInfo net_info;
1451 const int wait_time = 1000; /* msecs */
1452 int max_retries = secs_timeout * 1000 / wait_time; /* number of repeats
1453 until timeout */
1454 int retries = 0;
1455 int servers = 0;
1456 MEASURE_TIME_START
1457 while (servers != expected_count && retries < max_retries) {
1458 WRITE_LOG("Counting number of servers \"" << service <<
1459 "\" with dtab \"" << dtab <<
1460 "\" and port " << port << ", ip " << ANNOUNCEMENT_HOST <<
1461 " via service discovery "
1462 "(expecting " << expected_count <<
1463 " servers found). Retry #" << retries);
1464 servers = 0;
1465 /* Check that the server is actually announced and enabled */
1466 auto announced_srvrs = s_GetAnnouncedServers(false, { service }),
1467 enabled_srvrs = s_GetAnnouncedServers(true, { service });
1468 bool serv_enabled = false, serv_announced = false;
1469 for (unsigned short i = 0; i < announced_srvrs.size(); ++i) {
1470 if (announced_srvrs[i].port == port &&
1471 announced_srvrs[i].service == service) {
1472 serv_announced = true;
1473 break;
1474 }
1475 }
1476 for (unsigned short i = 0; i < enabled_srvrs.size(); ++i) {
1477 if (enabled_srvrs[i].port == port &&
1478 enabled_srvrs[i].service == service) {
1479 serv_enabled = true;
1480 break;
1481 }
1482 }
1483 if (retries > 0) { /* for the first cycle we do not sleep */
1484 #ifdef NCBI_THREADS
1485 SleepMilliSec(wait_time);
1486 #else
1487 /* Answer healthcheck a few times */
1488 for (int i = 0; i < 10; i++) {
1489 s_HealthcheckThread->AnswerHealthcheck();
1490 };
1491 #endif /* NCBI_THREADS */
1492 }
1493 const SSERV_Info* info;
1494
1495 if (dtab.length() > 1) {
1496 ConnNetInfo_SetUserHeader(*net_info, dtab.c_str());
1497 } else {
1498 ConnNetInfo_SetUserHeader(*net_info, "DTab-Local: ");
1499 }
1500 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
1501 SERV_LOCALHOST, 0, 0.0,
1502 *net_info, 0, 0, 0, 0, 0));
1503 do {
1504 info = SERV_GetNextInfoEx(*iter, NULL);
1505 if (info != NULL && info->port == port)
1506 servers++;
1507 } while (info != NULL);
1508 MEASURE_TIME_FINISH
1509 WRITE_LOG("Found " << servers << " servers of service "
1510 << service << ", port " << port << " after "
1511 << time_elapsed << " seconds via service discovery.\n"
1512 << "This service is " << (serv_announced ? "" : "NOT ")
1513 << "announced and is " << (serv_enabled ? "" : "NOT ")
1514 << "enabled.");
1515 retries++;
1516 }
1517 /* If we did not find the expected amount of servers, there will be an error
1518 * (just if to think logically).
1519 * To easier find what went wrong - save line of code that called
1520 * s_CountServersWithExpectation(), port, count and expected count */
1521 if (servers != expected_count) {
1522 SLBOSResolutionError err;
1523 err.code_line = code_line;
1524 err.count = servers;
1525 err.expected_count = expected_count;
1526 err.port = port;
1527 s_ResolutionErrors.push_back(err);
1528 }
1529 return servers;
1530 }
1531
1532 ///////////////////////////////////////////////////////////////////////////////
1533 ////////////// DECLARATIONS //////////////////////////
1534 ///////////////////////////////////////////////////////////////////////////////
1535 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1536 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1537 namespace ResetIterator
1538 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1539 {
1540 /* 1. Should make capacity of elements in data->cand equal zero
1541 * 2. Should be able to reset iter N times consequently without crash
1542 * 3. Should be able to "reset iter, then getnextinfo" N times
1543 * consequently without crash */
1544 void NoConditions__IterContainsZeroCandidates();
1545 void MultipleReset__ShouldNotCrash();
1546 void Multiple_AfterGetNextInfo__ShouldNotCrash();
1547 } /* namespace ResetIterator */
1548
1549
1550 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1551 namespace CloseIterator
1552 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1553 {
1554 /* 1. Should work immediately after Open
1555 * 2. Should work immediately after Reset
1556 * 3. Should work immediately after Open, GetNextInfo
1557 * 4. Should work immediately after Open, GetNextInfo, Reset */
1558 void AfterOpen__ShouldWork();
1559 void AfterReset__ShouldWork();
1560 void AfterGetNextInfo__ShouldWork();
1561 void FullCycle__ShouldWork();
1562 } /* namespace CloseIterator */
1563
1564
1565 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1566 namespace DTab
1567 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1568 /* 1. Mix of registry DTab and HTTP Dtab: registry goes first */
1569 {
1570 void DTabRegistryAndHttp__RegistryGoesFirst();
1571 void NonStandardVersion__FoundWithDTab();
1572 }
1573
1574 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1575 namespace ResolveViaLBOS
1576 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1577 {
1578 /* 1. Should return string with IP:port if OK
1579 * 2. Should return NULL if LBOS answered "not found"
1580 * 3. Should return NULL if LBOS is not reachable
1581 * 4. Should be able to support up to M IP:port combinations
1582 (not checking for repeats) with storage overhead not more than same
1583 as size needed (that is, all space consumed is twice as size needed,
1584 used and unused space together)
1585 * 5. Should be able to skip answer of LBOS if it is corrupt or contains
1586 not valid data */
1587 void ServiceExists__ReturnHostIP();
1588 void ServiceDoesNotExist__ReturnNULL();
1589 void NoLBOS__ReturnNULL();
1590 void FakeMassiveInput__ShouldProcess();
1591 void FakeErrorInput__ShouldNotCrash();
1592 } /* namespace ResolveViaLBOS */
1593
1594
1595 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1596 namespace GetLBOSAddress
1597 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1598 {
1599 /* 1. If specific way to find LBOS is specified, try it first. If failed,
1600 search LBOS's address in default order
1601 * 2. If custom host is specified as method but is not provided as value,
1602 search LBOS's address in default order
1603 * 3. Default order is: search LBOS's address first in registry. If
1604 failed, try 127.0.0.1:8080. If failed, try /etc/ncbi/{role, domain}. */
1605 void SpecificMethod__FirstInResult();
1606 void CustomHostNotProvided__SkipCustomHost();
1607 void NoConditions__AddressDefOrder();
1608 } /* namespace GetLBOSAddress */
1609
1610
1611 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1612 namespace GetCandidates
1613 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1614 {
1615 /* 1. Iterate through received LBOS's addresses, if there is no response
1616 from current LBOS
1617 * 2. If one LBOS works, do not try another LBOS
1618 * 3. If *net_info was provided for Serv_OpenP, the same *net_info should be
1619 available while getting candidates via LBOS to provide DTABs. */
1620 void LBOSNoResponse__SkipLBOS();
1621 void LBOSResponds__Finish();
1622 void NetInfoProvided__UseNetInfo();
1623 } /* namespace GetCandidates */
1624
1625
1626 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1627 namespace GetNextInfo
1628 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1629 {
1630 /* 1. If no candidates found yet, or reset was just made, get candidates
1631 and return first
1632 * 2. If no candidates found yet, or reset was just made, and unrecoverable
1633 error while getting candidates, return 0
1634 * 3. If candidates already found, return next
1635 * 4. If last candidate was already returned, return 0
1636 * 5. If data is NULL for some reason, construct new data
1637 * 6 .If SERV_MapperName(*iter) returns name of another mapper, return NULL */
1638 void EmptyCands__RunGetCandidates();
1639 void ErrorUpdating__ReturnNull();
1640 void HaveCands__ReturnNext();
1641 void LastCandReturned__ReturnNull();
1642 void DataIsNull__ReconstructData();
1643 void WrongMapper__ReturnNull();
1644 } /* namespace GetNextInfo */
1645
1646
1647 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1648 namespace Open
1649 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1650 {
1651 /* 1. If *net_info is NULL, construct own *net_info
1652 * 2. If read from LBOS successful, return s_op
1653 * 3. If read from LBOS successful and info pointer != NULL, write
1654 first element NULL to info
1655 * 4. If read from LBOS unsuccessful or no such service, return 0 */
1656 void NetInfoNull__ConstructNetInfo();
1657 void ServerExists__ReturnLbosOperations();
1658 void InfoPointerProvided__WriteNull();
1659 void NoSuchService__ReturnNull();
1660 } /* namespace Open */
1661
1662
1663 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1664 namespace GeneralLBOS
1665 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1666 {
1667 /* 1. If server exists in LBOS, it should be found and s_op should be
1668 * returned by SERV_OpenP()
1669 * 2. If server does not exist in LBOS, it should not be found and
1670 * SERV_OpenP() should return NULL
1671 * 3. If most priority LBOS can be found, it should be used used for
1672 * resolution */
1673 void ServerExists__ShouldReturnLbosOperations();
1674 void ServerDoesNotExist__ShouldReturnNull();
1675 void LbosExist__ShouldWork();
1676 } /* namespace GeneralLBOS */
1677
1678
1679
1680 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1681 namespace Announcement
1682 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1683 {
1684 /* 1. Successfully announced: return SUCCESS
1685 * 2. Successfully announced: SLBOS_AnnounceHandle deannounce_handle
1686 * contains info needed to later deannounce announced server
1687 * 3. Successfully announced: char* lbos_answer contains answer of LBOS
1688 * 4. Successfully announced: information about announcement is saved to
1689 * hidden LBOS mapper's storage
1690 * 5. Could not find LBOS: return NO_LBOS
1691 * 6. Could not find LBOS: char* lbos_answer is set to NULL
1692 * 7. Could not find LBOS: SLBOS_AnnounceHandle deannounce_handle is set to
1693 * NULL
1694 * 8. LBOS returned error: return LBOS_ERROR
1695 * 9. LBOS returned error: char* lbos_answer contains answer of LBOS
1696 * 10. LBOS returned error: SLBOS_AnnounceHandle deannounce_handle is set to
1697 * NULL
1698 * 11. Server announced again (service name, IP and port coincide) and
1699 * announcement in the same zone, replace old info about announced
1700 * server in internal storage with new one.
1701 * 12. Server announced again and trying to announce in another
1702 * zone - return MULTIZONE_ANNOUNCE_PROHIBITED
1703 * 13. Was passed incorrect healthcheck URL (NULL or empty not starting with
1704 * "http(s)://"): do not announce and return INVALID_ARGS
1705 * 14. Was passed incorrect port (zero): do not announce and return
1706 * INVALID_ARGS
1707 * 15. Was passed incorrect version(NULL or empty): do not announce and
1708 * return INVALID_ARGS
1709 * 16. Was passed incorrect service nameNULL or empty): do not announce and
1710 * return INVALID_ARGS
1711 * 17. Real-life test: after announcement server should be visible to
1712 * resolve
1713 * 18. If was passed "0.0.0.0" as IP, should replace it with local IP or
1714 * hostname
1715 * 19. Was passed "0.0.0.0" as IP and could not manage to resolve local host
1716 * IP: do not announce and return DNS_RESOLVE_ERROR
1717 * 20. LBOS is OFF - return eLBOS_Disabled
1718 * 21. Announced successfully, but LBOS return corrupted answer -
1719 * return SERVER_ERROR
1720 * 22. Trying to announce server and providing dead healthcheck URL -
1721 * return eLbosNotFound
1722 * 23. Trying to announce server and providing dead healthcheck URL -
1723 * server should not be announced
1724 * 24. Announce server with separate host and healtcheck - should be found in
1725 * %LBOS%/text/service */
1726 void AllOK__ReturnSuccess();
1727 void AllOK__DeannounceHandleProvided();
1728 void AllOK__LBOSAnswerProvided();
1729 void AllOK__AnnouncedServerSaved();
1730 void NoLBOS__ReturnNoLBOSAndNotFind();
1731 void NoLBOS__LBOSAnswerNull();
1732 void NoLBOS__DeannounceHandleNull();
1733 void LBOSErrorCode__ReturnServerErrorCode();
1734 void LBOSError__LBOSAnswerProvided();
1735 void LBOSError__DeannounceHandleNull();
1736 void AlreadyAnnouncedInTheSameZone__ReplaceInStorage();
1737 void ForeignDomain__NoAnnounce();
1738 void AlreadyAnnouncedInAnotherZone__ReturnMultizoneProhibited();
1739 void IncorrectURL__ReturnInvalidArgs();
1740 void IncorrectPort__ReturnInvalidArgs();
1741 void IncorrectVersion__ReturnInvalidArgs();
1742 void IncorrectServiceName__ReturnInvalidArgs();
1743 void RealLife__VisibleAfterAnnounce();
1744 void ResolveLocalIPError__ReturnDNSError();
1745 void IP0000__ReplaceWithIP();
1746 void LBOSOff__ReturnKLBOSOff();
1747 void LBOSAnnounceCorruptOutput__ReturnServerError();
1748 void HealthcheckDead__ReturnKLBOSSuccess();
1749 void HealthcheckDead__AnnouncementOK();
1750
1751 }
1752
1753 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1754 namespace AnnouncementRegistry
1755 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1756 {
1757 void TestNullOrEmptyField(const char* field_tested);
1758 /* 1. All parameters good (Custom section has all parameters correct in
1759 config) - return eLBOS_Success
1760 2. Custom section has nothing in config - return eLBOS_InvalidArgs
1761 3. Section empty or NULL (should use default section and return
1762 eLBOS_Success)
1763 4. Service is empty or NULL - return eLBOS_InvalidArgs
1764 5. Version is empty or NULL - return eLBOS_InvalidArgs
1765 6. port is empty or NULL - return eLBOS_InvalidArgs
1766 7. port is out of range - return eLBOS_InvalidArgs
1767 8. port contains letters - return eLBOS_InvalidArgs
1768 9. healthcheck is empty or NULL - return eLBOS_InvalidArgs
1769 10. healthcheck does not start with http:// or https:// - return
1770 eLBOS_InvalidArgs */
1771 void ParamsGood__ReturnSuccess();
1772 void CustomSectionNoVars__ReturnInvalidArgs();
1773 void CustomSectionEmptyOrNullAndDefaultSectionIsOk__ReturnSuccess();
1774 void ServiceEmptyOrNull__ReturnInvalidArgs();
1775 void VersionEmptyOrNull__ReturnInvalidArgs();
1776 void PortEmptyOrNull__ReturnInvalidArgs();
1777 void PortOutOfRange__ReturnInvalidArgs();
1778 void PortContainsLetters__ReturnInvalidArgs();
1779 void HealthchecktEmptyOrNull__ReturnInvalidArgs();
1780 void HealthcheckDoesNotStartWithHttp__ReturnInvalidArgs();
1781 }
1782
1783 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1784 namespace Deannouncement
1785 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1786 {
1787 /* 1. Successfully de-announced : return 1
1788 * 2. Successfully de-announced : if announcement was saved in local storage,
1789 * remove it
1790 * 3. Could not connect to provided LBOS : fail and return 0
1791 * 4. Successfully connected to LBOS, but deannounce returned error : return 0
1792 * 5. Real - life test : after de-announcement server should be invisible
1793 * to resolve
1794 * 6. Another domain - do not deannounce
1795 * 7. Deannounce without IP specified - deannounce from local host
1796 * 8. LBOS is OFF - return eLBOS_Disabled */
1797 void Deannounced__Return1(unsigned short port);
1798 void Deannounced__AnnouncedServerRemoved();
1799 void NoLBOS__Return0();
1800 void LBOSExistsDeannounce404__Return404();
1801 void RealLife__InvisibleAfterDeannounce();
1802 void ForeignDomain__DoNothing();
1803 void NoHostProvided__LocalAddress();
1804 }
1805
1806
1807 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1808 namespace DeannouncementAll
1809 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1810 {
1811 /* 1. If function was called and no servers were announced after call, no
1812 announced servers should be found in LBOS */
1813 void AllDeannounced__NoSavedLeft();
1814 }
1815
1816
1817 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1818 namespace Initialization
1819 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1820 {
1821 /* 1. Multithread simultaneous SERV_LBOS_Open() when LBOS is not yet
1822 * initialized should not crash
1823 * 2. At initialization if no LBOS found, mapper must turn OFF
1824 * 3. At initialization if LBOS found, mapper should be ON
1825 * 4. If LBOS has not yet been initialized, it should be initialized
1826 * at SERV_LBOS_Open()
1827 * 5. If LBOS turned OFF, it MUST return NULL on SERV_LBOS_Open()
1828 * 6. s_LBOS_InstancesList MUST not be NULL at beginning of s_LBOS_
1829 * Initialize()
1830 * 7. s_LBOS_InstancesList MUST not be NULL at beginning of
1831 * s_LBOS_FillCandidates()
1832 * 8. s_LBOS_FillCandidates() should switch first and good LBOS
1833 * addresses, if first is not responding
1834 */
1835 /** Multithread simultaneous SERV_LBOS_Open() when LBOS is not yet
1836 * initialized should not crash */
1837 void MultithreadInitialization__ShouldNotCrash();
1838 /** At initialization if no LBOS found, mapper must turn OFF */
1839 void InitializationFail__TurnOff();
1840 /** At initialization if LBOS found, mapper should be ON */
1841 void InitializationSuccess__StayOn();
1842 /** If LBOS has not yet been initialized, it should be initialized at
1843 * SERV_LBOS_Open(). */
1844 void OpenNotInitialized__ShouldInitialize();
1845 /** If LBOS turned OFF, it MUST return NULL on SERV_LBOS_Open(). */
1846 void OpenWhenTurnedOff__ReturnNull();
1847 /** s_LBOS_InstancesList MUST not be NULL at beginning of
1848 * s_LBOS_Initialize() */
1849 void s_LBOS_Initialize__s_LBOS_InstancesListNotNULL();
1850 /** s_LBOS_InstancesList MUST not be NULL at beginning of
1851 * s_LBOS_FillCandidates() */
1852 void s_LBOS_FillCandidates__s_LBOS_InstancesListNotNULL();
1853 } /* namespace LBOSMapperInit */
1854
1855
1856 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1857 namespace Configure
1858 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1859 {
1860 /* 1. Set version the check version - should show the version that was just set */
1861 void SetThenCheck__ShowsSetVersion();
1862 /* 2. Check version, that set different version, then check version -
1863 * should show new version */
1864 void CheckSetNewCheck__ChangesVersion();
1865 /* 3. Set version, check that it was set, then delete version - check
1866 * that no version exists */
1867 void DeleteThenCheck__SetExistsFalse();
1868 /* 4. Announce two servers with different version. First set one version
1869 * and discover server with that version. Then set the second version
1870 * and discover server with that version. */
1871 void AnnounceThenChangeVersion__DiscoverAnotherServer();
1872 /* 5. Announce one server. Discover it. Then delete version. Try to
1873 * discover it again, should not find.*/
1874 void AnnounceThenDeleteVersion__DiscoverFindsNothing();
1875 /* 6. Set with no service - invalid args */
1876 void SetNoService__InvalidArgs();
1877 /* 7. Get with no service - invalid args */
1878 void GetNoService__InvalidArgs();
1879 /* 8. Delete with no service - invalid args */
1880 void DeleteNoService__InvalidArgs();
1881 /* 9. Set with empty version - OK */
1882 void SetEmptyVersion__OK();
1883 /* 10. Set with empty version no service - invalid args */
1884 void SetNoServiceEmptyVersion__InvalidArgs();
1885 /* 11. Get, set, delete with service that does not exist, providing
1886 * "exists" parameter - this parameter should be false and version
1887 * should be empty */
1888 void ServiceNotExistsAndBoolProvided__EqualsFalse();
1889 /* 12. Get, set, delete with service that does exist, providing
1890 * "exists" parameter - this parameter should be true and version
1891 * should be filled */
1892 void ServiceExistsAndBoolProvided__EqualsTrue();
1893 /* 13. Get, set, delete with service that does not exist, not providing
1894 * "exists" parameter - version should be empty and no crash should
1895 * happen*/
1896 void ServiceNotExistsAndBoolNotProvided__NoCrash();
1897 /* 14. Get, set, delete with service that does exist, not providing
1898 * "exists" parameter - this parameter should be true and version
1899 * should be filled */
1900 void ServiceExistsAndBoolNotProvided__NoCrash();
1901 }
1902
1903
1904 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1905 namespace Stability
1906 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1907 {
1908 /* 1. Open, get all hosts, reset, get all hosts ... repeat N times
1909 * 2. (Open, (get all hosts, reset: repeat N times), close: repeat M times) */
1910 void GetNext_Reset__ShouldNotCrash();
1911 void FullCycle__ShouldNotCrash();
1912 } /* namespace Stability */
1913
1914
1915 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1916 namespace Performance
1917 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1918 {
1919 /* 1. (get all hosts, reset) times a second, dependency on number of threads
1920 * 2. (Open, get all hosts, reset, close) times a second, dependency on
1921 number of threads */
1922 void FullCycle__ShouldNotCrash();
1923 } /* namespace Performance */
1924
1925
1926 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1927 namespace MultiThreading
1928 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
1929 {
1930 void TryMultiThread(); /* namespace MultiThreading */
1931 }
1932
1933
1934 ///////////////////////////////////////////////////////////////////////////////
1935 ////////////// DEFINITIONS //////////////////////////
1936 ///////////////////////////////////////////////////////////////////////////////
1937 namespace AnnounceMetadata
1938 {
KnownMetaSpecFunc__SeeMetaInDescovery()1939 void KnownMetaSpecFunc__SeeMetaInDescovery()
1940 {
1941 CConnNetInfo net_info;
1942 const SSERV_Info* info;
1943 string version = "1.0.0";
1944 string service = s_GetUnknownService();
1945 string dtab = "DTab-local: " + service + "=>/zk#" + service + "/" + version;
1946 ConnNetInfo_SetUserHeader(*net_info, dtab.c_str());
1947 CCObjHolder<char> lbos_address(g_LBOS_GetLBOSAddress());
1948 string lbos_addr(lbos_address.Get());
1949 string expected_path = "myextra";
1950 unsigned short port = 8080;
1951 unsigned short rate = 200;
1952 string health = string("http://") + ANNOUNCEMENT_HOST + ":8080/health";
1953 /* Extra */
1954 LBOS::CMetaData meta;
1955 meta.SetExtra(expected_path);
1956 meta.SetType(LBOS::CMetaData::eHTTP);
1957 meta.SetRate(rate);
1958 s_AnnounceCPP(service, version, ANNOUNCEMENT_HOST, port, health, meta);
1959 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
1960 SERV_LOCALHOST, 0, 0.0,
1961 *net_info, 0, 0, 0, 0, 0));
1962 NCBITEST_REQUIRE_MESSAGE_MT_SAFE(*iter!=NULL, "Announced server not found");
1963 info = SERV_GetNextInfoEx(*iter, NULL);
1964 /* Extra */
1965 const char* real_path_cstr = SERV_HTTP_PATH(&info->u.http);
1966 NCBITEST_REQUIRE_MESSAGE_MT_SAFE(real_path_cstr != NULL, "Extra is empty!");
1967 string real_path = real_path_cstr;
1968 NCBITEST_CHECK_EQUAL_MT_SAFE(real_path, expected_path);
1969 /* Type */
1970 NCBITEST_CHECK_EQUAL_MT_SAFE(info->type, fSERV_Http);
1971 /* Rate */
1972 NCBITEST_CHECK_EQUAL_MT_SAFE(info->rate, rate);
1973
1974 s_DeannounceCPP(service, version, ANNOUNCEMENT_HOST, port);
1975 }
1976
KnownMetaMainFunc__SeeMetaInDiscovery()1977 void KnownMetaMainFunc__SeeMetaInDiscovery()
1978 {
1979 CConnNetInfo net_info;
1980 const SSERV_Info* info;
1981 string version = "1.0.0";
1982 string service = s_GetUnknownService();
1983 string dtab = "DTab-local: " + service + "=>/zk#" + service + "/" + version;
1984 ConnNetInfo_SetUserHeader(*net_info, dtab.c_str());
1985 CCObjHolder<char> lbos_address(g_LBOS_GetLBOSAddress());
1986 string lbos_addr(lbos_address.Get());
1987 string expected_path = "myextra";
1988 unsigned short port = 8080;
1989 unsigned short rate = 200;
1990 string health = string("http://") + ANNOUNCEMENT_HOST + ":8080/health";
1991 /* Extra */
1992 LBOS::CMetaData meta;
1993 meta.Set("extra", expected_path);
1994 meta.Set("type", "HTTP");
1995 meta.Set("rate", NStr::IntToString(rate));
1996 s_AnnounceCPP(service, version, ANNOUNCEMENT_HOST, port, health, meta);
1997 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
1998 SERV_LOCALHOST, 0, 0.0,
1999 *net_info, 0, 0, 0, 0, 0));
2000 NCBITEST_REQUIRE_MESSAGE_MT_SAFE(*iter!=NULL, "Announced server not found");
2001 info = SERV_GetNextInfoEx(*iter, NULL);
2002 /* Extra */
2003 const char* real_path_cstr = SERV_HTTP_PATH(&info->u.http);
2004 NCBITEST_REQUIRE_MESSAGE_MT_SAFE(real_path_cstr != NULL, "Extra is empty!");
2005 string real_path = real_path_cstr;
2006 NCBITEST_CHECK_EQUAL_MT_SAFE(real_path, expected_path);
2007 /* Type */
2008 NCBITEST_CHECK_EQUAL_MT_SAFE(info->type, fSERV_Http);
2009 /* Rate */
2010 NCBITEST_CHECK_EQUAL_MT_SAFE(info->rate, 200);
2011
2012 s_DeannounceCPP(service, version, ANNOUNCEMENT_HOST, port);
2013 }
2014
UnknownMetaMainFunc__SeeMetaInDiscovery()2015 void UnknownMetaMainFunc__SeeMetaInDiscovery()
2016 {
2017 CConnNetInfo net_info;
2018 string version = "1.0.0";
2019 string service = s_GetUnknownService();
2020 string dtab = "DTab-local: " + service + "=>/zk#" + service + "/" + version;
2021 ConnNetInfo_SetUserHeader(*net_info, dtab.c_str());
2022 CCObjHolder<char> lbos_address(g_LBOS_GetLBOSAddress());
2023 string lbos_addr(lbos_address.Get());
2024 string expected_path = "myextra";
2025 unsigned short port = 8080;
2026 string health = string("http://") + ANNOUNCEMENT_HOST + ":8080/health";
2027 /* Extra */
2028 LBOS::CMetaData meta;
2029 meta.Set("mymeta1", "meta");
2030 meta.Set("meta with spaces", "word1 word2");
2031 meta.Set("meta with end of line", "line1\nline2");
2032 meta.Set("meta with tab", "part1\tpart2");
2033
2034 s_AnnounceCPP(service, version, ANNOUNCEMENT_HOST, port, health, meta);
2035
2036 /* Check response from LBOS */
2037 s_WaitTillAnnounced(service, *net_info, 0, 0);
2038 CCObjHolder<char> lbos_output_orig(g_LBOS_UnitTesting_GetLBOSFuncs()->
2039 UrlReadAll(*net_info,
2040 (string("http://") + lbos_addr +
2041 "/lbos/v3/services" + service).c_str(),
2042 NULL, NULL));
2043 string lbos_output = *lbos_output_orig;
2044 /* Search for mymeta1 */
2045 string expected1 = "\"meta with spaces\":\"word1 word2\"",
2046 expected2 = "\"meta with end of line\":\"line1\\nline2\"",
2047 expected3 = "\"meta with tab\":\"part1\\tpart2\"",
2048 expected4 = "\"mymeta1\":\"meta\"";
2049
2050 size_t find_pos1 = lbos_output.find(expected1),
2051 find_pos2 = lbos_output.find(expected2),
2052 find_pos3 = lbos_output.find(expected3),
2053 find_pos4 = lbos_output.find(expected4);
2054 NCBITEST_CHECK_NE_MT_SAFE(find_pos1, string::npos);
2055 NCBITEST_CHECK_NE_MT_SAFE(find_pos2, string::npos);
2056 NCBITEST_CHECK_NE_MT_SAFE(find_pos3, string::npos);
2057 NCBITEST_CHECK_NE_MT_SAFE(find_pos4, string::npos);
2058 s_DeannounceCPP(service, version, ANNOUNCEMENT_HOST, port);
2059 }
2060
KnownAndUnknown__SeeMetaInDiscovery()2061 void KnownAndUnknown__SeeMetaInDiscovery()
2062 {
2063 CConnNetInfo net_info;
2064 const SSERV_Info* info;
2065 string version = "1.0.0";
2066 string service = s_GetUnknownService();
2067 string dtab = "DTab-local: " + service + "=>/zk#" + service + "/" + version;
2068 ConnNetInfo_SetUserHeader(*net_info, dtab.c_str());
2069 CCObjHolder<char> lbos_address(g_LBOS_GetLBOSAddress());
2070 string lbos_addr(lbos_address.Get());
2071 string expected_path = "myextra";
2072 unsigned short port = 8080;
2073 unsigned short rate = 200;
2074 string health = string("http://") + ANNOUNCEMENT_HOST + ":8080/health";
2075
2076 /* Extra */
2077 LBOS::CMetaData meta;
2078 meta.Set("mymeta1", "meta");
2079 meta.Set("meta with spaces", "word1 word2");
2080 meta.Set("meta with end of line", "line1\nline2");
2081 meta.Set("meta with tab", "part1\tpart2");
2082 meta.SetExtra(expected_path);
2083 meta.SetType(LBOS::CMetaData::eHTTP);
2084 meta.SetRate(rate);
2085 s_AnnounceCPP(service, version, ANNOUNCEMENT_HOST, port, health, meta);
2086
2087 /* Check known */
2088 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
2089 SERV_LOCALHOST, 0, 0.0,
2090 *net_info, 0, 0, 0, 0, 0));
2091 NCBITEST_REQUIRE_MESSAGE_MT_SAFE(*iter!=NULL, "Announced server not found");
2092 info = SERV_GetNextInfoEx(*iter, NULL);
2093 /* Extra */
2094 const char* real_path_cstr = SERV_HTTP_PATH(&info->u.http);
2095 NCBITEST_CHECK_MESSAGE_MT_SAFE(real_path_cstr != NULL, "Extra is empty!");
2096 if (real_path_cstr != NULL) {
2097 string real_path = real_path_cstr;
2098 NCBITEST_CHECK_EQUAL_MT_SAFE(real_path, expected_path);
2099 }
2100 /* Type */
2101 NCBITEST_CHECK_EQUAL_MT_SAFE(info->type, fSERV_Http);
2102 /* Rate */
2103 NCBITEST_CHECK_EQUAL_MT_SAFE(info->rate, 200);
2104
2105 /* Check unknown */
2106 /* Check response from LBOS */
2107 s_WaitTillAnnounced(service, *net_info, 0, 0);
2108 CCObjHolder<char> lbos_output_orig(g_LBOS_UnitTesting_GetLBOSFuncs()->
2109 UrlReadAll(*net_info,
2110 (string("http://") + lbos_addr +
2111 "/lbos/v3/services"+service).c_str(),
2112 NULL, NULL));
2113 string lbos_output = *lbos_output_orig;
2114 /* Search for mymeta1 */
2115 string expected1 = "\"meta with spaces\":\"word1 word2\"",
2116 expected2 = "\"meta with end of line\":\"line1\\nline2\"",
2117 expected3 = "\"meta with tab\":\"part1\\tpart2\"",
2118 expected4 = "\"mymeta1\":\"meta\"";
2119
2120 size_t find_pos1 = lbos_output.find(expected1),
2121 find_pos2 = lbos_output.find(expected2),
2122 find_pos3 = lbos_output.find(expected3),
2123 find_pos4 = lbos_output.find(expected4);
2124 NCBITEST_CHECK_NE_MT_SAFE(find_pos1, string::npos);
2125 NCBITEST_CHECK_NE_MT_SAFE(find_pos2, string::npos);
2126 NCBITEST_CHECK_NE_MT_SAFE(find_pos3, string::npos);
2127 NCBITEST_CHECK_NE_MT_SAFE(find_pos4, string::npos);
2128 s_DeannounceCPP(service, version, ANNOUNCEMENT_HOST, port);
2129 }
2130
DeleteMeta__NotSeeMetaInMetastring()2131 void DeleteMeta__NotSeeMetaInMetastring()
2132 {
2133 unsigned short rate = 200;
2134
2135 /* 1 */
2136 LBOS::CMetaData meta;
2137 string meta_string;
2138 meta.Set("mymeta1", "meta");
2139 meta.Set("mymeta1", "");
2140 meta.SetRate(rate);
2141 meta.Set("rate", "");
2142 meta.SetExtra("myextra2");
2143 meta.SetExtra("");
2144 meta.SetType(LBOS::CMetaData::eHTTP_POST);
2145 meta.SetType(LBOS::CMetaData::eNone);
2146 meta_string = meta.GetMetaString();
2147 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string());
2148
2149 /* 2 */
2150 meta.Set("mymeta1", "meta");
2151 meta.Set("mymeta1", "");
2152 meta.Set("rate", "200");
2153 meta.SetRate(0);
2154 meta.Set("extra", "myextra2");
2155 meta.Set("extra", "");
2156 meta.SetType("HTTP_POST");
2157 meta.SetType("");
2158 meta_string = meta.GetMetaString();
2159 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string());
2160
2161 /* 3 */
2162 meta.Set("mymeta1", "meta");
2163 meta.Set("mymeta1", "");
2164 meta.Set("rate", "200");
2165 meta.Set("rate", "");
2166 meta.Set("extra", "myextra2");
2167 meta.Set("extra", "");
2168 meta.Set("type", "HTTP_POST");
2169 meta.Set("type", "");
2170 meta_string = meta.GetMetaString();
2171 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string());
2172 }
2173
SetTypeBadEnumVal__Exception()2174 void SetTypeBadEnumVal__Exception()
2175 {
2176 LBOS::CMetaData meta;
2177
2178 ExceptionComparator<CLBOSException::eInvalidArgs, eLBOS_InvalidArgs>
2179 comparator("Unknown EHostType value. If you are sure that a correct "
2180 "value is used, please tell the developer about this "
2181 "issue\n");
2182 BOOST_CHECK_EXCEPTION(meta.SetType(-1), CLBOSException, comparator);
2183 BOOST_CHECK_EXCEPTION(meta.SetType(7), CLBOSException, comparator);
2184 BOOST_CHECK_EXCEPTION(meta.SetType(10), CLBOSException, comparator);
2185 BOOST_CHECK_EXCEPTION(meta.SetType(15), CLBOSException, comparator);
2186 }
2187
MetaNull__NoMetaInDiscovery()2188 void MetaNull__NoMetaInDiscovery()
2189 {
2190 CConnNetInfo net_info;
2191 string version = "1.0.0";
2192 string service = s_GetUnknownService();
2193 string dtab = "DTab-local: " + service + "=>/zk#" + service + "/" + version;
2194 ConnNetInfo_SetUserHeader(*net_info, dtab.c_str());
2195 CCObjHolder<char> lbos_address(g_LBOS_GetLBOSAddress());
2196 string lbos_addr(lbos_address.Get());
2197 string expected_path = "myextra";
2198 unsigned short port = 8080;
2199 string health = string("http://") + ANNOUNCEMENT_HOST + ":8080/health";
2200
2201 CCObjHolder<char> lbos_answer(NULL);
2202 CCObjHolder<char> lbos_status_message(NULL);
2203 s_AnnounceC(service.c_str(), version.c_str(), (ANNOUNCEMENT_HOST).c_str(),
2204 port, health.c_str(), NULL, &lbos_answer.Get(),
2205 &lbos_status_message.Get());
2206
2207 /* Check HTTP output */
2208 s_WaitTillAnnounced(service, *net_info, 0, 0);
2209 CCObjHolder<char> lbos_output_orig(g_LBOS_UnitTesting_GetLBOSFuncs()->
2210 UrlReadAll(*net_info,
2211 (string("http://") + lbos_addr +
2212 "/lbos/v3/services" + service).c_str(),
2213 NULL, NULL));
2214 string lbos_output = *lbos_output_orig;
2215 /* Search for mymeta1 */
2216 string expected = "\"port\":8080},\"meta\":{}}]";
2217 size_t find_pos = lbos_output.find(expected);
2218 NCBITEST_CHECK_NE_MT_SAFE(find_pos, string::npos);
2219
2220 s_DeannounceCPP(service, version, ANNOUNCEMENT_HOST, port);
2221 }
2222
NoMetaProvided__NoMetaInDiscovery()2223 void NoMetaProvided__NoMetaInDiscovery()
2224 {
2225 CConnNetInfo net_info;
2226 string version = "1.0.0";
2227 string service = s_GetUnknownService();
2228 string dtab = "DTab-local: " + service + "=>/zk#" + service + "/" + version;
2229 ConnNetInfo_SetUserHeader(*net_info, dtab.c_str());
2230 CCObjHolder<char> lbos_address(g_LBOS_GetLBOSAddress());
2231 string lbos_addr(lbos_address.Get());
2232 string expected_path = "myextra";
2233 unsigned short port = 8080;
2234 string health = string("http://") + ANNOUNCEMENT_HOST + ":8080/health";
2235
2236 CCObjHolder<char> lbos_answer(NULL);
2237 CCObjHolder<char> lbos_status_message(NULL);
2238 s_AnnounceCPP(service.c_str(), version.c_str(), (ANNOUNCEMENT_HOST).c_str(),
2239 port, health.c_str());
2240
2241 /* Check HTTP output */
2242 s_WaitTillAnnounced(service, *net_info, 0, 0);
2243 CCObjHolder<char> lbos_output_orig(g_LBOS_UnitTesting_GetLBOSFuncs()->
2244 UrlReadAll(*net_info,
2245 (string("http://") + lbos_addr +
2246 "/lbos/v3/services" + service).c_str(),
2247 NULL, NULL));
2248 string lbos_output = *lbos_output_orig;
2249 /* Search for mymeta1 */
2250 string expected = "\"port\":8080},\"meta\":{}}]";
2251 size_t find_pos = lbos_output.find(expected);
2252 NCBITEST_CHECK_NE_MT_SAFE(find_pos, string::npos);
2253
2254 s_DeannounceCPP(service, version, ANNOUNCEMENT_HOST, port);
2255 }
2256
SetTypeValidVal__SeeMetaInDiscovery()2257 void SetTypeValidVal__SeeMetaInDiscovery()
2258 {
2259 LBOS::CMetaData meta;
2260 string meta_string;
2261 LBOS::CMetaData::EHostType host_type;
2262 string host_type_str, host_type_meta;
2263
2264 /* 0 */
2265 meta.SetType(LBOS::CMetaData::eNone);
2266 host_type = meta.GetType();
2267 host_type_str = meta.GetType(true);
2268 host_type_meta = meta.Get("type");
2269 meta_string = meta.GetMetaString();
2270
2271 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string(""));
2272 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string(""));
2273 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string(""));
2274 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eNone);
2275
2276 /* 1 */
2277 meta.SetType(LBOS::CMetaData::eHTTP);
2278 host_type = meta.GetType();
2279 host_type_str = meta.GetType(true);
2280 host_type_meta = meta.Get("type");
2281 meta_string = meta.GetMetaString();
2282
2283 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string("HTTP"));
2284 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string("HTTP"));
2285 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string("type=HTTP"));
2286 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eHTTP);
2287
2288 /* 2 */
2289 meta.SetType(LBOS::CMetaData::eHTTP_POST);
2290 host_type = meta.GetType();
2291 host_type_str = meta.GetType(true);
2292 host_type_meta = meta.Get("type");
2293 meta_string = meta.GetMetaString();
2294
2295 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string("HTTP_POST"));
2296 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string("HTTP_POST"));
2297 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string("type=HTTP_POST"));
2298 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eHTTP_POST);
2299
2300 /* 3 */
2301 meta.SetType(LBOS::CMetaData::eStandalone);
2302 host_type = meta.GetType();
2303 host_type_str = meta.GetType(true);
2304 host_type_meta = meta.Get("type");
2305 meta_string = meta.GetMetaString();
2306
2307 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string("STANDALONE"));
2308 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string("STANDALONE"));
2309 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string("type=STANDALONE"));
2310 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eStandalone);
2311
2312 /* 4 */
2313 meta.SetType(LBOS::CMetaData::eNCBID);
2314 host_type = meta.GetType();
2315 host_type_str = meta.GetType(true);
2316 host_type_meta = meta.Get("type");
2317 meta_string = meta.GetMetaString();
2318
2319 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string("NCBID"));
2320 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string("NCBID"));
2321 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string("type=NCBID"));
2322 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eNCBID);
2323
2324 /* 5 */
2325 meta.SetType(LBOS::CMetaData::eDNS);
2326 host_type = meta.GetType();
2327 host_type_str = meta.GetType(true);
2328 host_type_meta = meta.Get("type");
2329 meta_string = meta.GetMetaString();
2330
2331 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string("DNS"));
2332 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string("DNS"));
2333 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string("type=DNS"));
2334 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eDNS);
2335
2336 /* 6 */
2337 ExceptionComparator<CLBOSException::eInvalidArgs, eLBOS_InvalidArgs>
2338 comparator("Unknown EHostType value. If you are sure that a correct "
2339 "value is used, please tell the developer about this "
2340 "issue\n");
2341 BOOST_CHECK_EXCEPTION(meta.SetType(LBOS::CMetaData::eUnknown),
2342 CLBOSException, comparator);
2343
2344 /* String */
2345 /* 0 */
2346 meta.SetType("");
2347 host_type = meta.GetType();
2348 host_type_str = meta.GetType(true);
2349 host_type_meta = meta.Get("type");
2350 meta_string = meta.GetMetaString();
2351
2352 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string(""));
2353 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string(""));
2354 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string(""));
2355 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eNone);
2356
2357 /* 1 */
2358 meta.SetType("HTTP");
2359 host_type = meta.GetType();
2360 host_type_str = meta.GetType(true);
2361 host_type_meta = meta.Get("type");
2362 meta_string = meta.GetMetaString();
2363
2364 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string("HTTP"));
2365 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string("HTTP"));
2366 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string("type=HTTP"));
2367 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eHTTP);
2368
2369 /* 2 */
2370 meta.SetType("HTTP_POST");
2371 host_type = meta.GetType();
2372 host_type_str = meta.GetType(true);
2373 host_type_meta = meta.Get("type");
2374 meta_string = meta.GetMetaString();
2375
2376 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string("HTTP_POST"));
2377 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string("HTTP_POST"));
2378 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string("type=HTTP_POST"));
2379 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eHTTP_POST);
2380
2381 /* 3 */
2382 meta.SetType("sTanDalone");
2383 host_type = meta.GetType();
2384 host_type_str = meta.GetType(true);
2385 host_type_meta = meta.Get("type");
2386 meta_string = meta.GetMetaString();
2387
2388 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string("STANDALONE"));
2389 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string("STANDALONE"));
2390 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string("type=STANDALONE"));
2391 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eStandalone);
2392
2393 /* 4 */
2394 meta.SetType("ncbid");
2395 host_type = meta.GetType();
2396 host_type_str = meta.GetType(true);
2397 host_type_meta = meta.Get("type");
2398 meta_string = meta.GetMetaString();
2399
2400 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string("NCBID"));
2401 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string("NCBID"));
2402 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string("type=NCBID"));
2403 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eNCBID);
2404
2405 /* 5 */
2406 meta.SetType("DnS");
2407 host_type = meta.GetType();
2408 host_type_str = meta.GetType(true);
2409 host_type_meta = meta.Get("type");
2410 meta_string = meta.GetMetaString();
2411
2412 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string("DNS"));
2413 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string("DNS"));
2414 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string("type=DNS"));
2415 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eDNS);
2416
2417 /* 6 */
2418 meta.SetType("MyType");
2419 host_type = meta.GetType();
2420 host_type_str = meta.GetType(true);
2421 host_type_meta = meta.Get("type");
2422 meta_string = meta.GetMetaString();
2423
2424 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string("MYTYPE"));
2425 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string("MYTYPE"));
2426 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string("type=MYTYPE"));
2427 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eUnknown);
2428
2429 /* Set() */
2430 /* 0 */
2431 meta.Set("type", "");
2432 host_type = meta.GetType();
2433 host_type_str = meta.GetType(true);
2434 host_type_meta = meta.Get("type");
2435 meta_string = meta.GetMetaString();
2436 meta_string = meta.GetMetaString();
2437
2438 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string(""));
2439 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string(""));
2440 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string(""));
2441 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eNone);
2442
2443 /* 1 */
2444 meta.Set("type", "HTTP");
2445 host_type = meta.GetType();
2446 host_type_str = meta.GetType(true);
2447 host_type_meta = meta.Get("type");
2448 meta_string = meta.GetMetaString();
2449
2450 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string("HTTP"));
2451 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string("HTTP"));
2452 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string("type=HTTP"));
2453 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eHTTP);
2454
2455 /* 2 */
2456 meta.Set("type", "HTTP_POST");
2457 host_type = meta.GetType();
2458 host_type_str = meta.GetType(true);
2459 host_type_meta = meta.Get("type");
2460 meta_string = meta.GetMetaString();
2461
2462 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string("HTTP_POST"));
2463 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string("HTTP_POST"));
2464 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string("type=HTTP_POST"));
2465 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eHTTP_POST);
2466
2467 /* 3 */
2468 meta.Set("type", "sTanDalone");
2469 host_type = meta.GetType();
2470 host_type_str = meta.GetType(true);
2471 host_type_meta = meta.Get("type");
2472 meta_string = meta.GetMetaString();
2473
2474 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string("sTanDalone"));
2475 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string("STANDALONE"));
2476 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string("type=sTanDalone"));
2477 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eStandalone);
2478
2479 /* 4 */
2480 meta.Set("type", "ncbid");
2481 host_type = meta.GetType();
2482 host_type_str = meta.GetType(true);
2483 host_type_meta = meta.Get("type");
2484 meta_string = meta.GetMetaString();
2485
2486 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string("ncbid"));
2487 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string("NCBID"));
2488 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string("type=ncbid"));
2489 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eNCBID);
2490
2491 /* 5 */
2492 meta.Set("type", "DnS");
2493 host_type = meta.GetType();
2494 host_type_str = meta.GetType(true);
2495 host_type_meta = meta.Get("type");
2496 meta_string = meta.GetMetaString();
2497
2498 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string("DnS"));
2499 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string("DNS"));
2500 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string("type=DnS"));
2501 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eDNS);
2502
2503 /* 6 */
2504 meta.Set("type", "MyType");
2505 host_type = meta.GetType();
2506 host_type_str = meta.GetType(true);
2507 host_type_meta = meta.Get("type");
2508 meta_string = meta.GetMetaString();
2509
2510 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_meta, string("MyType"));
2511 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type_str, string("MYTYPE"));
2512 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string("type=MyType"));
2513 NCBITEST_CHECK_EQUAL_MT_SAFE(host_type, LBOS::CMetaData::eUnknown);
2514 }
2515
SetTypeEmpty__TypeStandaloneInDiscovery()2516 void SetTypeEmpty__TypeStandaloneInDiscovery()
2517 {
2518 CConnNetInfo net_info;
2519 string version = "1.0.0";
2520 string service = s_GetUnknownService();
2521 string dtab = "DTab-local: " + service + "=>/zk#" + service + "/" + version;
2522 ConnNetInfo_SetUserHeader(*net_info, dtab.c_str());
2523 CCObjHolder<char> lbos_address(g_LBOS_GetLBOSAddress());
2524 string lbos_addr(lbos_address.Get());
2525 unsigned short port = 8080;
2526 string health = string("http://") + ANNOUNCEMENT_HOST + ":8080/health";
2527 string expected = "\"type\":\"HTTP\"";
2528 LBOS::CMetaData meta;
2529 size_t find_pos;
2530 string lbos_output;
2531 int retries = 0;
2532
2533 /* Announce with type */
2534 meta.SetType(LBOS::CMetaData::eHTTP);
2535 s_AnnounceCPP(service.c_str(), version.c_str(), (ANNOUNCEMENT_HOST).c_str(),
2536 port, health.c_str(), meta);
2537
2538 /* Check HTTP output */
2539 s_WaitTillAnnounced(service, *net_info, 0, 0);
2540 CCObjHolder<char> lbos_output_orig1(g_LBOS_UnitTesting_GetLBOSFuncs()->
2541 UrlReadAll(*net_info,
2542 (string("http://") + lbos_addr +
2543 "/lbos/v3/services"+service).c_str(),
2544 NULL, NULL));
2545 lbos_output = *lbos_output_orig1;
2546 find_pos = lbos_output.find(expected);
2547 NCBITEST_CHECK_NE_MT_SAFE(find_pos, string::npos);
2548
2549
2550 /* Announce without type */
2551 meta.SetType(LBOS::CMetaData::eNone);
2552 s_AnnounceCPP(service.c_str(), version.c_str(), (ANNOUNCEMENT_HOST).c_str(),
2553 port, health.c_str(), meta);
2554
2555 /* Check HTTP output */
2556 /* Since the server is already announced, we cannot use
2557 s_WaitTillAnnounced(), so we just do retries */
2558 find_pos = string::npos;
2559 while (find_pos == string::npos && retries++ < 5) {
2560 CCObjHolder<char> lbos_output_orig2(g_LBOS_UnitTesting_GetLBOSFuncs()->
2561 UrlReadAll(*net_info,
2562 (string("http://") + lbos_addr +
2563 "/lbos/v3/services"+service).c_str(),
2564 NULL, NULL));
2565 lbos_output = *lbos_output_orig2;
2566 find_pos = lbos_output.find(expected);
2567 if (find_pos == string::npos)
2568 SleepMilliSec(100);
2569 }
2570 NCBITEST_CHECK_EQUAL_MT_SAFE(find_pos, string::npos);
2571 s_DeannounceCPP(service, version, ANNOUNCEMENT_HOST, port);
2572 }
2573
SetExtraEmpty__ExtraChangesToEmpty()2574 void SetExtraEmpty__ExtraChangesToEmpty()
2575 {
2576 CConnNetInfo net_info;
2577 unsigned short port = s_GeneratePort();
2578 string version = "1.0.0";
2579 string service = s_GetUnknownService();
2580 string dtab = "DTab-local: " + service + "=>/zk#" + service + "/" + version;
2581 ConnNetInfo_SetUserHeader(*net_info, dtab.c_str());
2582 CCObjHolder<char> lbos_address(g_LBOS_GetLBOSAddress());
2583 string lbos_addr(lbos_address.Get());
2584 string health = string("http://") + ANNOUNCEMENT_HOST + ":8080/health";
2585 string expected = "\"extra\":\"test_extra\"";
2586 LBOS::CMetaData meta;
2587 size_t find_pos;
2588 string lbos_output;
2589 int retries = 0;
2590
2591 /* Announce with type */
2592 meta.SetExtra("test_extra");
2593 s_AnnounceCPP(service.c_str(), version.c_str(), (ANNOUNCEMENT_HOST).c_str(),
2594 port, health.c_str(), meta);
2595
2596 /* Check HTTP output */
2597 s_WaitTillAnnounced(service, *net_info, 0, 0);
2598 CCObjHolder<char> lbos_output_orig1(g_LBOS_UnitTesting_GetLBOSFuncs()->
2599 UrlReadAll(*net_info,
2600 (string("http://") + lbos_addr +
2601 "/lbos/v3/services"+service).c_str(),
2602 NULL, NULL));
2603 lbos_output = *lbos_output_orig1;
2604 find_pos = lbos_output.find(expected);
2605 NCBITEST_CHECK_NE_MT_SAFE(find_pos, string::npos);
2606
2607
2608 /* Announce without type */
2609 meta.SetExtra("");
2610 s_AnnounceCPP(service.c_str(), version.c_str(), (ANNOUNCEMENT_HOST).c_str(),
2611 port, health.c_str(), meta);
2612
2613 /* Check HTTP output */
2614 /* Since the server is already announced, we cannot use
2615 s_WaitTillAnnounced(), so we just do retries */
2616 find_pos = string::npos;
2617 while (find_pos == string::npos && retries++ < 5) {
2618 CCObjHolder<char> lbos_output_orig2(g_LBOS_UnitTesting_GetLBOSFuncs()->
2619 UrlReadAll(*net_info,
2620 (string("http://") + lbos_addr +
2621 "/lbos/v3/services"+service).c_str(),
2622 NULL, NULL));
2623 lbos_output = *lbos_output_orig2;
2624 find_pos = lbos_output.find(expected);
2625 if (find_pos == string::npos)
2626 SleepMilliSec(100);
2627 }
2628 NCBITEST_CHECK_EQUAL_MT_SAFE(find_pos, string::npos);
2629
2630 s_DeannounceCPP(service, version, ANNOUNCEMENT_HOST, port);
2631 }
2632
Set__CaseInsensitive()2633 void Set__CaseInsensitive()
2634 {
2635 LBOS::CMetaData meta;
2636 string extra, meta_string, mymeta;
2637
2638 /* 1 */
2639 meta.Set("ExTrA", "extra_val1");
2640 meta.Set("MyMeTa", "meta_val1");
2641 meta_string = meta.GetMetaString();
2642 extra = meta.Get("extra");
2643 mymeta = meta.Get("mymeta");
2644 NCBITEST_CHECK_EQUAL_MT_SAFE(extra, string("extra_val1"));
2645 NCBITEST_CHECK_EQUAL_MT_SAFE(mymeta, string("meta_val1"));
2646 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string,
2647 string("extra=extra_val1&mymeta=meta_val1"));
2648
2649 /* 2 */
2650 meta.Set("eXTrA", "extra_val2");
2651 meta.Set("Mymeta", "meta_val2");
2652 meta_string = meta.GetMetaString();
2653 extra = meta.Get("extra");
2654 mymeta = meta.Get("mymeta");
2655 NCBITEST_CHECK_EQUAL_MT_SAFE(extra, string("extra_val2"));
2656 NCBITEST_CHECK_EQUAL_MT_SAFE(mymeta, string("meta_val2"));
2657 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string,
2658 string("extra=extra_val2&mymeta=meta_val2"));
2659
2660 /* 3 */
2661 meta.Set("EXTRA", "extra_val3");
2662 meta.Set("MYMETA", "meta_val3");
2663 meta_string = meta.GetMetaString();
2664 extra = meta.Get("extra");
2665 mymeta = meta.Get("mymeta");
2666 NCBITEST_CHECK_EQUAL_MT_SAFE(extra, string("extra_val3"));
2667 NCBITEST_CHECK_EQUAL_MT_SAFE(mymeta, string("meta_val3"));
2668 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string,
2669 string("extra=extra_val3&mymeta=meta_val3"));
2670
2671 /* 4 */
2672 meta.Set("extra", "extra_val4");
2673 meta.Set("mymeta", "meta_val4");
2674 meta_string = meta.GetMetaString();
2675 extra = meta.Get("extra");
2676 mymeta = meta.Get("mymeta");
2677 NCBITEST_CHECK_EQUAL_MT_SAFE(extra, string("extra_val4"));
2678 NCBITEST_CHECK_EQUAL_MT_SAFE(mymeta, string("meta_val4"));
2679 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string,
2680 string("extra=extra_val4&mymeta=meta_val4"));
2681 }
2682
GetDefaultMetas__DefaultValEmpty()2683 void GetDefaultMetas__DefaultValEmpty()
2684 {
2685 LBOS::CMetaData meta;
2686
2687 /* Extra */
2688 string extra = meta.GetExtra();
2689 NCBITEST_CHECK_EQUAL_MT_SAFE(extra, string(""));
2690
2691 /* Type */
2692 string type_str = meta.GetType(true);
2693 LBOS::CMetaData::EHostType type = meta.GetType();
2694 NCBITEST_CHECK_EQUAL_MT_SAFE(type_str, string());
2695 NCBITEST_CHECK_EQUAL_MT_SAFE(type, LBOS::CMetaData::eNone);
2696
2697 /* Rate */
2698 double rate = meta.GetRate();
2699 NCBITEST_CHECK_EQUAL_MT_SAFE(rate, 0);
2700
2701 /* Unknown*/
2702 string mymeta = meta.Get("mymeta");
2703 NCBITEST_CHECK_EQUAL_MT_SAFE(mymeta, string());
2704 }
2705
GetMetaString__ValuesAsExpected()2706 void GetMetaString__ValuesAsExpected()
2707 {
2708 LBOS::CMetaData meta;
2709 string meta_string;
2710
2711 /* rate and extra */
2712 meta.SetRate(100);
2713 meta.SetExtra("myextra");
2714 meta_string = meta.GetMetaString();
2715 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string("extra=myextra&rate=100"));
2716 meta.SetRate(0);
2717 meta.SetExtra("");
2718 meta_string = meta.GetMetaString();
2719 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string());
2720
2721 /* extra */
2722 meta.SetExtra("myextra");
2723 meta_string = meta.GetMetaString();
2724 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string("extra=myextra"));
2725 meta.SetExtra("");
2726 meta_string = meta.GetMetaString();
2727 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string());
2728
2729 /* type and extra */
2730 meta.SetType("mytype");
2731 meta.SetExtra("myextra");
2732 meta_string = meta.GetMetaString();
2733 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string,
2734 string("extra=myextra&type=MYTYPE"));
2735 meta.SetType("");
2736 meta.SetExtra("");
2737 meta_string = meta.GetMetaString();
2738 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string());
2739
2740 /* mymeta1 and mymeta2 */
2741 meta.Set("mymeta1", "mymetaval1");
2742 meta.Set("mymeta2", "mymetaval2");
2743 meta_string = meta.GetMetaString();
2744 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string,
2745 string("mymeta1=mymetaval1&mymeta2=mymetaval2"));
2746 meta.Set("mymeta1", "");
2747 meta.Set("mymeta2", "");
2748 meta_string = meta.GetMetaString();
2749 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string());
2750
2751 /* rate and extra and mymeta1 and mymeta2 */
2752 meta.SetRate(100);
2753 meta.SetExtra("myextra");
2754 meta.Set("mymeta1", "mymetaval1");
2755 meta.Set("mymeta2", "mymetaval2");
2756 meta_string = meta.GetMetaString();
2757 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string,
2758 string("extra=myextra&mymeta1=mymetaval1&mymeta2=mymetaval2&rate=100"));
2759 meta.SetExtra("");
2760 meta.SetRate(0);
2761 meta.Set("mymeta1", "");
2762 meta.Set("mymeta2", "");
2763 meta_string = meta.GetMetaString();
2764 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string());
2765
2766 /* rate and extra and type and mymeta1 and mymeta2 */
2767 meta.SetRate(100);
2768 meta.SetExtra("myextra");
2769 meta.Set("mymeta1", "mymetaval1");
2770 meta.Set("mymeta2", "mymetaval2");
2771 meta.Set("type", "mytype");
2772 meta_string = meta.GetMetaString();
2773 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string,
2774 string("extra=myextra&mymeta1=mymetaval1&"
2775 "mymeta2=mymetaval2&rate=100&type=mytype"));
2776 meta.SetExtra("");
2777 meta.SetRate(0);
2778 meta.SetType("");
2779 meta.Set("mymeta1", "");
2780 meta.Set("mymeta2", "");
2781 meta_string = meta.GetMetaString();
2782 NCBITEST_CHECK_EQUAL_MT_SAFE(meta_string, string());
2783 }
2784
SetNotMeta__Exception()2785 void SetNotMeta__Exception()
2786 {
2787 LBOS::CMetaData meta;
2788 ExceptionComparator<CLBOSException::eInvalidArgs, eLBOS_InvalidArgs>
2789 comparator("This name cannot be used for metadata\n");
2790 /* version */
2791 BOOST_CHECK_EXCEPTION(meta.Set("version","val"),CLBOSException, comparator);
2792 /* ip */
2793 BOOST_CHECK_EXCEPTION(meta.Set("ip", "val"), CLBOSException, comparator);
2794 /* port */
2795 BOOST_CHECK_EXCEPTION(meta.Set("port", "val"), CLBOSException, comparator);
2796 /* check */
2797 BOOST_CHECK_EXCEPTION(meta.Set("check", "val"), CLBOSException, comparator);
2798 /* format */
2799 BOOST_CHECK_EXCEPTION(meta.Set("format","val"), CLBOSException, comparator);
2800 /* name */
2801 BOOST_CHECK_EXCEPTION(meta.Set("name", "val"), CLBOSException, comparator);
2802 }
2803
2804
ExtraOrTypeWhitespace__ThrowException()2805 void ExtraOrTypeWhitespace__ThrowException()
2806 {
2807 LBOS::CMetaData meta;
2808 ExceptionComparator<CLBOSException::eInvalidArgs, eLBOS_InvalidArgs>
2809 comp_extra("This convenience function throws on whitespace "
2810 "characters in \"extra\" meta parameter. If you know "
2811 "what you are doing, you can use CMetaData::Set"
2812 "(\"extra\", ...)\n");
2813 ExceptionComparator<CLBOSException::eInvalidArgs, eLBOS_InvalidArgs>
2814 comp_type("This convenience function throws on whitespace "
2815 "characters in \"type\" meta parameter. If you know "
2816 "what you are doing, you can use CMetaData::Set"
2817 "(\"type\", ...)\n");
2818
2819 /* Extra */
2820 /* Space */
2821 BOOST_CHECK_EXCEPTION(meta.SetExtra("a a"), CLBOSException, comp_extra);
2822
2823 /* Tab */
2824 BOOST_CHECK_EXCEPTION(meta.SetExtra("a\ta"), CLBOSException, comp_extra);
2825
2826 /* Newline */
2827 BOOST_CHECK_EXCEPTION(meta.SetExtra("a\na"), CLBOSException, comp_extra);
2828
2829 /* Vertical tab */
2830 BOOST_CHECK_EXCEPTION(meta.SetExtra("a\va"), CLBOSException, comp_extra);
2831
2832 /* Feed */
2833 BOOST_CHECK_EXCEPTION(meta.SetExtra("a\fa"), CLBOSException, comp_extra);
2834
2835 /* Carriage return */
2836 BOOST_CHECK_EXCEPTION(meta.SetExtra("a\ra"), CLBOSException, comp_extra);
2837
2838 /* Type */
2839 /* Space */
2840 BOOST_CHECK_EXCEPTION(meta.SetType("a a"), CLBOSException, comp_type);
2841
2842 /* Tab */
2843 BOOST_CHECK_EXCEPTION(meta.SetType("a\ta"), CLBOSException, comp_type);
2844
2845 /* Newline */
2846 BOOST_CHECK_EXCEPTION(meta.SetType("a\na"), CLBOSException, comp_type);
2847
2848 /* Vertical tab */
2849 BOOST_CHECK_EXCEPTION(meta.SetType("a\va"), CLBOSException, comp_type);
2850
2851 /* Feed */
2852 BOOST_CHECK_EXCEPTION(meta.SetType("a\fa"), CLBOSException, comp_type);
2853
2854 /* Carriage return */
2855 BOOST_CHECK_EXCEPTION(meta.SetType("a\ra"), CLBOSException, comp_type);
2856 }
2857
SetWithWhitespace__SeeInDiscovery()2858 void SetWithWhitespace__SeeInDiscovery()
2859 {
2860 CConnNetInfo net_info;
2861 string version = "1.0.0";
2862 string service = s_GetUnknownService();
2863 string dtab = "DTab-local: " + service + "=>/zk#" + service + "/" + version;
2864 ConnNetInfo_SetUserHeader(*net_info, dtab.c_str());
2865 CCObjHolder<char> lbos_address(g_LBOS_GetLBOSAddress());
2866 string lbos_addr(lbos_address.Get());
2867 string expected;
2868 unsigned short port = 8080;
2869 string health = string("http://") + ANNOUNCEMENT_HOST + ":8080/health";
2870 /* Extra */
2871 LBOS::CMetaData meta;
2872 string lbos_output;
2873 size_t find_pos;
2874
2875 /* space */
2876 meta.Set("extra", "a a");
2877 meta.Set("type", "a a");
2878 s_AnnounceCPP(service, version, ANNOUNCEMENT_HOST, port, health, meta);
2879 /* Check HTTP output */
2880 s_WaitTillAnnounced(service, *net_info, 0, 0);
2881 CCObjHolder<char> lbos_output_orig0(g_LBOS_UnitTesting_GetLBOSFuncs()->
2882 UrlReadAll(*net_info,
2883 (string("http://") + lbos_addr +
2884 "/lbos/v3/services"+service).c_str(),
2885 NULL, NULL));
2886 expected = "\"extra\":\"a a\",\"type\":\"a a\"";
2887 lbos_output = *lbos_output_orig0;
2888 find_pos = lbos_output.find(expected);
2889 NCBITEST_CHECK_NE_MT_SAFE(find_pos, string::npos);
2890 s_DeannounceCPP(service, version, ANNOUNCEMENT_HOST, port);
2891
2892 /* Tab */
2893 meta.Set("extra", "a\ta");
2894 meta.Set("type", "a\ta");
2895 s_AnnounceCPP(service, version, ANNOUNCEMENT_HOST, port, health, meta);
2896 /* Check HTTP output */
2897 s_WaitTillAnnounced(service, *net_info, 0, 0);
2898 CCObjHolder<char> lbos_output_orig1(g_LBOS_UnitTesting_GetLBOSFuncs()->
2899 UrlReadAll(*net_info,
2900 (string("http://") + lbos_addr +
2901 "/lbos/v3/services"+service).c_str(),
2902 NULL, NULL));
2903 expected = "\"extra\":\"a\\ta\",\"type\":\"a\\ta\"";
2904 lbos_output = *lbos_output_orig1;
2905 find_pos = lbos_output.find(expected);
2906 NCBITEST_CHECK_NE_MT_SAFE(find_pos, string::npos);
2907 s_DeannounceCPP(service, version, ANNOUNCEMENT_HOST, port);
2908
2909 /* Newline */
2910 meta.Set("extra", "a\na");
2911 meta.Set("type", "a\na");
2912 s_AnnounceCPP(service, version, ANNOUNCEMENT_HOST, port, health, meta);
2913 /* Check HTTP output */
2914 s_WaitTillAnnounced(service, *net_info, 0, 0);
2915 CCObjHolder<char> lbos_output_orig2(g_LBOS_UnitTesting_GetLBOSFuncs()->
2916 UrlReadAll(*net_info,
2917 (string("http://") + lbos_addr +
2918 "/lbos/v3/services"+service).c_str(),
2919 NULL, NULL));
2920 expected = "\"extra\":\"a\\na\",\"type\":\"a\\na\"";
2921 lbos_output = *lbos_output_orig2;
2922 find_pos = lbos_output.find(expected);
2923 NCBITEST_CHECK_NE_MT_SAFE(find_pos, string::npos);
2924 s_DeannounceCPP(service, version, ANNOUNCEMENT_HOST, port);
2925
2926 /* Vertical tab */
2927 meta.Set("extra", "a\va");
2928 meta.Set("type", "a\va");
2929 s_AnnounceCPP(service, version, ANNOUNCEMENT_HOST, port, health, meta);
2930 /* Check HTTP output */
2931 s_WaitTillAnnounced(service, *net_info, 0, 0);
2932 CCObjHolder<char> lbos_output_orig3(g_LBOS_UnitTesting_GetLBOSFuncs()->
2933 UrlReadAll(*net_info,
2934 (string("http://") + lbos_addr +
2935 "/lbos/v3/services"+service).c_str(),
2936 NULL, NULL));
2937 expected = "\"extra\":\"a\\u000Ba\",\"type\":\"a\\u000Ba\"";
2938 lbos_output = *lbos_output_orig3;
2939 find_pos = lbos_output.find(expected);
2940 NCBITEST_CHECK_NE_MT_SAFE(find_pos, string::npos);
2941 s_DeannounceCPP(service, version, ANNOUNCEMENT_HOST, port);
2942
2943 /* Feed */
2944 meta.Set("extra", "a\fa");
2945 meta.Set("type", "a\fa");
2946 s_AnnounceCPP(service, version, ANNOUNCEMENT_HOST, port, health, meta);
2947 /* Check HTTP output */
2948 s_WaitTillAnnounced(service, *net_info, 0, 0);
2949 CCObjHolder<char> lbos_output_orig4(g_LBOS_UnitTesting_GetLBOSFuncs()->
2950 UrlReadAll(*net_info,
2951 (string("http://") + lbos_addr +
2952 "/lbos/v3/services"+service).c_str(),
2953 NULL, NULL));
2954 expected = "\"extra\":\"a\\fa\",\"type\":\"a\\fa\"";
2955 lbos_output = *lbos_output_orig4;
2956 find_pos = lbos_output.find(expected);
2957 NCBITEST_CHECK_NE_MT_SAFE(find_pos, string::npos);
2958 s_DeannounceCPP(service, version, ANNOUNCEMENT_HOST, port);
2959
2960 /* Carriage return */
2961 meta.Set("extra", "a\ra");
2962 meta.Set("type", "a\ra");
2963 s_AnnounceCPP(service, version, ANNOUNCEMENT_HOST, port, health, meta);
2964 /* Check HTTP output */
2965 s_WaitTillAnnounced(service, *net_info, 0, 0);
2966 CCObjHolder<char> lbos_output_orig5(g_LBOS_UnitTesting_GetLBOSFuncs()->
2967 UrlReadAll(*net_info,
2968 (string("http://") + lbos_addr +
2969 "/lbos/v3/services"+service).c_str(),
2970 NULL, NULL));
2971 expected = "\"extra\":\"a\\ra\",\"type\":\"a\\ra\"";
2972 lbos_output = *lbos_output_orig5;
2973 find_pos = lbos_output.find(expected);
2974 NCBITEST_CHECK_NE_MT_SAFE(find_pos, string::npos);
2975 s_DeannounceCPP(service, version, ANNOUNCEMENT_HOST, port);
2976
2977 }
2978
2979
SetRateInvalidString__ThrowException()2980 void SetRateInvalidString__ThrowException()
2981 {
2982 LBOS::CMetaData meta;
2983 ExceptionComparator<CLBOSException::eInvalidArgs, eLBOS_InvalidArgs>
2984 comp_extra("Could not parse string value for SetRate\n");
2985
2986 BOOST_CHECK_EXCEPTION(meta.SetRate("integer"), CLBOSException, comp_extra);
2987 }
2988
2989
SetRateGetRateInt__AllOK()2990 void SetRateGetRateInt__AllOK()
2991 {
2992 LBOS::CMetaData meta;
2993 /* zero */
2994 meta.Set("rate", "0");
2995 NCBITEST_CHECK_EQUAL_MT_SAFE(meta.GetRate(), 0);
2996 /* positive */
2997 meta.Set("rate", "-100");
2998 NCBITEST_CHECK_EQUAL_MT_SAFE(meta.GetRate(), -100);
2999 /* negative */
3000 meta.Set("rate", "200");
3001 NCBITEST_CHECK_EQUAL_MT_SAFE(meta.GetRate(), 200);
3002 /* Double */
3003 meta.Set("rate", "0.1");
3004 NCBITEST_CHECK_EQUAL_MT_SAFE(meta.GetRate(), 0.1);
3005 meta.Set("rate", "103.7");
3006 NCBITEST_CHECK_EQUAL_MT_SAFE(meta.GetRate(), 103.7);
3007 /* negative double */
3008 meta.Set("rate", "-0.1");
3009 NCBITEST_CHECK_EQUAL_MT_SAFE(meta.GetRate(), -0.1);
3010 /* float point zero */
3011 meta.Set("rate", "0.0");
3012 NCBITEST_CHECK_EQUAL_MT_SAFE(meta.GetRate(), 0.0);
3013 }
3014
3015
SetRateGetRateNonInt__Exception()3016 void SetRateGetRateNonInt__Exception()
3017 {
3018 LBOS::CMetaData meta;
3019 ExceptionComparator<CLBOSException::eInvalidArgs, eLBOS_InvalidArgs>
3020 comparator("Value in \"rate\" meta parameter cannot be represented "
3021 "as an integer\n");
3022 /* String */
3023 meta.Set("rate", "myval");
3024 BOOST_CHECK_EXCEPTION(meta.GetRate(), CLBOSException, comparator);
3025 /* Wrong format */
3026 meta.Set("rate", "0,1");
3027 BOOST_CHECK_EXCEPTION(meta.GetRate(), CLBOSException, comparator);
3028 /* digits and letters mix */
3029 meta.Set("rate", "13-29a");
3030 BOOST_CHECK_EXCEPTION(meta.GetRate(), CLBOSException, comparator);
3031 }
3032
3033 /** 21. Announce from registry test - announce and see metedata in discovery */
AnnounceFromRegistry__SeeMetaInDiscovery()3034 void AnnounceFromRegistry__SeeMetaInDiscovery()
3035 {
3036 const SSERV_Info* info;
3037 string dtab = "DTab-local: /lbostest=>/zk#/lbostest/1.0.0";
3038 CConnNetInfo net_info;
3039 string service = "/lbostest";
3040 ConnNetInfo_SetUserHeader(*net_info, dtab.c_str());
3041 CCObjHolder<char> lbos_address(g_LBOS_GetLBOSAddress());
3042 string lbos_addr(lbos_address.Get());
3043 string expected_path = "myextra";
3044 string version = "1.0.0";
3045 unsigned short port = 8080;
3046 /*
3047 unsigned short rate = 200;
3048 string health = string("http://") + ANNOUNCEMENT_HOST + ":8080/health";*/
3049
3050 s_AnnounceCPPFromRegistry("SECTION_WITH_METADATA");
3051
3052 /* Check known */
3053 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
3054 SERV_LOCALHOST, 0, 0.0,
3055 *net_info, 0, 0, 0, 0, 0));
3056 NCBITEST_REQUIRE_MESSAGE_MT_SAFE(*iter!=NULL, "Announced server not found");
3057 info = SERV_GetNextInfoEx(*iter, NULL);
3058 /* Extra */
3059 const char* real_path_cstr = SERV_HTTP_PATH(&info->u.http);
3060 NCBITEST_CHECK_MESSAGE_MT_SAFE(real_path_cstr != NULL, "Extra is empty!");
3061 if (real_path_cstr != NULL) {
3062 string real_path = real_path_cstr;
3063 NCBITEST_CHECK_EQUAL_MT_SAFE(real_path, expected_path);
3064 }
3065 /* Type */
3066 NCBITEST_CHECK_EQUAL_MT_SAFE(info->type, fSERV_Http);
3067 /* Rate */
3068 NCBITEST_CHECK_EQUAL_MT_SAFE(info->rate, 200);
3069
3070 /* Check unknown */
3071 /* Check response from LBOS */
3072 s_WaitTillAnnounced(service, *net_info, 0, 0);
3073 CCObjHolder<char> lbos_output_orig(g_LBOS_UnitTesting_GetLBOSFuncs()->
3074 UrlReadAll(*net_info,
3075 (string("http://") + lbos_addr +
3076 "/lbos/v3/services"+service).c_str(),
3077 NULL, NULL));
3078 string lbos_output = *lbos_output_orig;
3079 /* Search for mymeta1 */
3080 string expected1 = "\"meta with spaces\":\"word1 word2\"",
3081 expected2 = "\"meta with end of line\":\"line1\\nline2\"",
3082 expected3 = "\"meta with tab\":\"part1\\tpart2\"",
3083 expected4 = "\"mymeta1\":\"meta\"";
3084
3085 size_t find_pos1 = lbos_output.find(expected1),
3086 find_pos2 = lbos_output.find(expected2),
3087 find_pos3 = lbos_output.find(expected3),
3088 find_pos4 = lbos_output.find(expected4);
3089 NCBITEST_CHECK_NE_MT_SAFE(find_pos1, string::npos);
3090 NCBITEST_CHECK_NE_MT_SAFE(find_pos2, string::npos);
3091 NCBITEST_CHECK_NE_MT_SAFE(find_pos3, string::npos);
3092 NCBITEST_CHECK_NE_MT_SAFE(find_pos4, string::npos);
3093
3094 s_DeannounceCPP(service, version, ANNOUNCEMENT_HOST, port);
3095 }
3096
3097 /** 22. */
RegistryNoSuchSection__Exception()3098 void RegistryNoSuchSection__Exception()
3099 {
3100 LBOS::CMetaData meta;
3101 ExceptionComparator<CLBOSException::eInvalidArgs, eLBOS_InvalidArgs>
3102 comparator("Could not parse port \"\" in section "
3103 "\"SECTION_DOESNOTEXIST\"\n");
3104
3105 BOOST_CHECK_EXCEPTION(s_AnnounceCPPFromRegistry("SECTION_DOESNOTEXIST"),
3106 CLBOSException, comparator);
3107 }
3108
3109 } /* namespace AnnounceMetadata */
3110
3111 namespace ExtraResolveData
3112 {
3113 struct SHostCheck
3114 {
3115 unsigned int host;
3116 bool check;
3117 };
3118
s_FakeInputTest(int servers_num)3119 static void s_FakeInputTest(int servers_num)
3120 {
3121 CLBOSStatus lbos_status(true, true);
3122 string service = "/service/doesnotexist";
3123 unsigned int temp_ip;
3124 unsigned short temp_port;
3125 CCounterResetter resetter(s_CallCounter);
3126 CConnNetInfo net_info;
3127 /*
3128 * We know that iter is LBOS's.
3129 */
3130 CCObjArrayHolder<SSERV_Info> hostports(
3131 g_LBOS_UnitTesting_GetLBOSFuncs()->ResolveIPPort(
3132 "lbosdevacvancbinlmnih.gov", "/lbos", *net_info));
3133 int i = 0;
3134 NCBITEST_CHECK_MESSAGE_MT_SAFE(*hostports != NULL,
3135 "Problem with fake massive input, "
3136 "no servers found. ");
3137 ostringstream temp_host;
3138 map<unsigned short, SHostCheck> hosts;
3139 for (i = 0; i < 200; i++) {
3140 temp_host.str("");
3141 temp_host << i+1 << "." << i+2 << "." << i+3 << "." << i+4
3142 << ":" << (i+1)*215;
3143 SOCK_StringToHostPort(temp_host.str().c_str(),
3144 &temp_ip,
3145 &temp_port);
3146 hosts[temp_port] = SHostCheck{ temp_ip, false };
3147 }
3148 if (*hostports) {
3149 for (i = 0; hostports[i] != NULL; i++) {
3150 SHostCheck& host_check = hosts[hostports[i]->port];
3151 NCBITEST_CHECK_MESSAGE_MT_SAFE(
3152 host_check.host == hostports[i]->host,
3153 "Problem with recognizing port or IP in massive input");
3154 if (host_check.host == hostports[i]->host) {
3155 host_check.check = true;
3156 }
3157 }
3158 i = 0;
3159 auto iter = hosts.begin();
3160 for (; iter != hosts.end(); iter++) {
3161 if (iter->second.check)
3162 i++;
3163 }
3164 stringstream ss;
3165 ss << "Mapper should find " << servers_num << " hosts, but found " << i;
3166 NCBITEST_CHECK_MESSAGE_MT_SAFE(i == servers_num, ss.str().c_str());
3167 }
3168 }
ExtraData__DoesNotCrash()3169 void ExtraData__DoesNotCrash()
3170 {
3171 CMockFunction<FLBOS_ConnReadMethod*> mock(
3172 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
3173 s_FakeReadDiscoveryExtra<200>);
3174 s_FakeInputTest(200);
3175 }
3176
EmptyExtra__DoesNotCrash()3177 void EmptyExtra__DoesNotCrash()
3178 {
3179 CMockFunction<FLBOS_ConnReadMethod*> mock(
3180 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
3181 s_FakeReadDiscoveryEmptyExtra<200>);
3182 s_FakeInputTest(200);
3183 }
3184
EmptyServInfoPart__Skip()3185 void EmptyServInfoPart__Skip()
3186 {
3187 CMockFunction<FLBOS_ConnReadMethod*> mock(
3188 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
3189 s_FakeReadDiscoveryEmptyServInfoPart<200>);
3190 s_FakeInputTest(0);
3191 }
3192 } /* namespace ExtraResolveData */
3193
3194 namespace ExceptionCodes
3195 {
CheckCodes()3196 void CheckCodes()
3197 {
3198 CLBOSException::EErrCode code;
3199 code = CLBOSException::s_HTTPCodeToEnum(400);
3200 NCBITEST_CHECK_EQUAL_MT_SAFE(code, CLBOSException::eBadRequest);
3201 code = CLBOSException::s_HTTPCodeToEnum(404);
3202 NCBITEST_CHECK_EQUAL_MT_SAFE(code, CLBOSException::eNotFound);
3203 code = CLBOSException::s_HTTPCodeToEnum(450);
3204 NCBITEST_CHECK_EQUAL_MT_SAFE(code, CLBOSException::eLbosNotFound);
3205 code = CLBOSException::s_HTTPCodeToEnum(451);
3206 NCBITEST_CHECK_EQUAL_MT_SAFE(code, CLBOSException::eDNSResolve);
3207 code = CLBOSException::s_HTTPCodeToEnum(452);
3208 NCBITEST_CHECK_EQUAL_MT_SAFE(code, CLBOSException::eInvalidArgs);
3209 code = CLBOSException::s_HTTPCodeToEnum(453);
3210 NCBITEST_CHECK_EQUAL_MT_SAFE(code, CLBOSException::eMemAlloc);
3211 code = CLBOSException::s_HTTPCodeToEnum(454);
3212 NCBITEST_CHECK_EQUAL_MT_SAFE(code, CLBOSException::eProtocol);
3213 code = CLBOSException::s_HTTPCodeToEnum(500);
3214 NCBITEST_CHECK_EQUAL_MT_SAFE(code, CLBOSException::eServer);
3215 code = CLBOSException::s_HTTPCodeToEnum(550);
3216 NCBITEST_CHECK_EQUAL_MT_SAFE(code, CLBOSException::eDisabled);
3217 /*
3218 * Some unknown
3219 */
3220 code = CLBOSException::s_HTTPCodeToEnum(200);
3221 NCBITEST_CHECK_EQUAL_MT_SAFE(code, CLBOSException::eUnknown);
3222 code = CLBOSException::s_HTTPCodeToEnum(204);
3223 NCBITEST_CHECK_EQUAL_MT_SAFE(code, CLBOSException::eUnknown);
3224 code = CLBOSException::s_HTTPCodeToEnum(401);
3225 NCBITEST_CHECK_EQUAL_MT_SAFE(code, CLBOSException::eUnknown);
3226 code = CLBOSException::s_HTTPCodeToEnum(503);
3227 NCBITEST_CHECK_EQUAL_MT_SAFE(code, CLBOSException::eUnknown);
3228 }
3229
3230
3231 /** Error codes - only for internal errors (that are not returned by
3232 * LBOS itself) */
CheckErrorCodeStrings()3233 void CheckErrorCodeStrings()
3234 {
3235 string error_string;
3236
3237 /* 400 */
3238 error_string = CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL,
3239 CLBOSException::eBadRequest, "",
3240 eLBOS_BadRequest).GetErrCodeString();
3241 NCBITEST_CHECK_EQUAL_MT_SAFE(error_string, "");
3242
3243 /* 404 */
3244 error_string = CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL,
3245 CLBOSException::eNotFound, "",
3246 eLBOS_BadRequest).GetErrCodeString();
3247 NCBITEST_CHECK_EQUAL_MT_SAFE(error_string, "");
3248
3249 /* 500 */
3250 error_string = CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL,
3251 CLBOSException::eServer, "",
3252 eLBOS_Server).GetErrCodeString();
3253 NCBITEST_CHECK_EQUAL_MT_SAFE(error_string, "");
3254
3255 /* 450 */
3256 error_string = CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL,
3257 CLBOSException::eLbosNotFound, "",
3258 eLBOS_BadRequest).GetErrCodeString();
3259 NCBITEST_CHECK_EQUAL_MT_SAFE(error_string, "LBOS was not found");
3260
3261 /* 451 */
3262 error_string = CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL,
3263 CLBOSException::
3264 eDNSResolve, "",
3265 eLBOS_BadRequest).GetErrCodeString();
3266 NCBITEST_CHECK_EQUAL_MT_SAFE(error_string, "DNS error. Possibly, cannot "
3267 "get IP of current machine or resolve "
3268 "provided hostname for the server");
3269 /* 452 */
3270 error_string = CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL,
3271 CLBOSException::eInvalidArgs, "",
3272 eLBOS_BadRequest).GetErrCodeString();
3273 NCBITEST_CHECK_EQUAL_MT_SAFE(error_string,
3274 "Invalid arguments were provided. No "
3275 "request to LBOS was sent");
3276
3277 /* 453 */
3278 error_string = CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL,
3279 CLBOSException::eMemAlloc, "",
3280 eLBOS_BadRequest).GetErrCodeString();
3281 NCBITEST_CHECK_EQUAL_MT_SAFE(error_string, "Memory allocation error happened "
3282 "while performing request");
3283
3284 /* 454 */
3285 error_string = CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL,
3286 CLBOSException::eProtocol, "",
3287 eLBOS_BadRequest).GetErrCodeString();
3288 NCBITEST_CHECK_EQUAL_MT_SAFE(error_string, "Failed to parse LBOS output.");
3289
3290 /* 550 */
3291 error_string = CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL,
3292 CLBOSException::eDisabled, "",
3293 eLBOS_BadRequest).GetErrCodeString();
3294 NCBITEST_CHECK_EQUAL_MT_SAFE(error_string,
3295 "LBOS functionality is turned OFF. Check "
3296 "config file or connection to LBOS.");
3297 /* unknown */
3298 error_string = CLBOSException(CDiagCompileInfo(__FILE__, __LINE__), NULL,
3299 CLBOSException::eUnknown, "",
3300 eLBOS_BadRequest).GetErrCodeString();
3301 NCBITEST_CHECK_EQUAL_MT_SAFE(error_string, "Unknown LBOS error code");
3302 }
3303 }
3304
3305 namespace IPCache
3306 {
3307 /** Announce with host empty - resolving works, gets host from healthcheck,
3308 * resolves host to IP and saves result to cache. We compare real
3309 * IP with what was saved in cache
3310 * @attention
3311 * No multithread, test uses private methods that are not thread-safe by
3312 * themselves */
HostInHealthcheck__TryFindReturnsHostIP()3313 void HostInHealthcheck__TryFindReturnsHostIP()
3314 {
3315 CLBOSStatus lbos_status(true, true);
3316 string lbos_answer;
3317 string node_name = s_GenerateNodeName();
3318 unsigned short port = kDefaultPort;
3319 WRITE_LOG("Announce host - resolving works and saves resolution result");
3320 /* Prepare for test. We need to be sure that there is no previously
3321 * registered non-deleted service. We count server with chosen port
3322 * and check if there is no server already announced */
3323 int count_before;
3324 SELECT_PORT(count_before, node_name, port);
3325
3326 /* Pre-cleanup */
3327 CLBOSIpCache::HostnameDelete(node_name, s_GetMyHost(), "1.0.0", port);
3328
3329 /* Test - announce, then check TryFind */
3330 BOOST_CHECK_NO_THROW(s_AnnounceCPPSafe(node_name, "1.0.0", "", port,
3331 string("http://") + s_GetMyHost() +
3332 ":" + s_PortStr(PORT_N) +
3333 "/health"));
3334 string IP = CLBOSIpCache::HostnameTryFind(node_name,
3335 s_GetMyHost(), "1.0.0", port);
3336 string my_ip = s_GetMyIP();
3337 NCBITEST_CHECK_EQUAL_MT_SAFE(my_ip, IP);
3338
3339 /* Cleanup */
3340 BOOST_CHECK_NO_THROW(s_DeannounceCPP(node_name, "1.0.0", "", port));
3341 }
3342
3343
3344 /** Announce with host difficult from the one in healthcheck - resolving works,
3345 * resolves host to IP and saves result to cache. We compare real IP
3346 * with what was saved in cache
3347 * @attention
3348 * No multithread, test uses private methods that are not thread-safe by
3349 * themselves */
HostSeparate__TryFindReturnsHostkIP()3350 void HostSeparate__TryFindReturnsHostkIP()
3351 {
3352 CLBOSStatus lbos_status(true, true);
3353 string lbos_answer;
3354 string node_name = s_GenerateNodeName();
3355 unsigned short port = kDefaultPort;
3356 WRITE_LOG("Announce host - resolving works and saves resolution result");
3357 /* Prepare for test. We need to be sure that there is no previously
3358 * registered non-deleted service. We count server with chosen port
3359 * and check if there is no server already announced */
3360 int count_before;
3361 SELECT_PORT(count_before, node_name, port);
3362
3363 /* Pre-cleanup */
3364 CLBOSIpCache::HostnameDelete(node_name, s_GetMyHost(), "1.0.0", port);
3365
3366 /* Test - announce, then check TryFind */
3367 BOOST_CHECK_NO_THROW(s_AnnounceCPPSafe(node_name, "1.0.0", s_GetMyHost(),
3368 port, string("http://") + "iebdev11"
3369 ":" + s_PortStr(PORT_N) + "/health"));
3370 string IP = CLBOSIpCache::HostnameTryFind(node_name,
3371 s_GetMyHost(), "1.0.0", port);
3372 string my_ip = s_GetMyIP();
3373 NCBITEST_CHECK_EQUAL_MT_SAFE(my_ip, IP);
3374
3375 /* Cleanup */
3376 BOOST_CHECK_NO_THROW(s_DeannounceCPP(node_name, "1.0.0", "", port));
3377 }
3378
3379
3380 /** Do not announce host - HostnameTryFind returns the same hostname.
3381 * @attention
3382 * No multithread, test uses private methods that are not thread-safe by
3383 * themselves */
NoHost__TryFindReturnsTheSame()3384 void NoHost__TryFindReturnsTheSame()
3385 {
3386 CLBOSStatus lbos_status(true, true);
3387 string lbos_answer;
3388 string node_name = s_GenerateNodeName();
3389 unsigned short port = kDefaultPort;
3390 WRITE_LOG("Announce host - resolving works and saves resolution result");
3391 /* Prepare for test. We need to be sure that there is no previously
3392 * registered non-deleted service. We count server with chosen port
3393 * and check if there is no server already announced */
3394 int count_before;
3395 SELECT_PORT(count_before, node_name, port);
3396
3397 /* Pre-cleanup */
3398 CLBOSIpCache::HostnameDelete(node_name, "cnn.com", "1.0.0", port);
3399
3400 /* Test - check TryFind without announcing */
3401 string IP = CLBOSIpCache::HostnameTryFind(node_name,
3402 s_GetMyHost(), "1.0.0", port);
3403 string my_host = s_GetMyHost();
3404 NCBITEST_CHECK_EQUAL_MT_SAFE(my_host, IP);
3405 }
3406
3407
3408 /** Common part for all tests that check if resolution works as meant to be
3409 * @attention
3410 * No multithread, test uses private methods that are not thread-safe by
3411 * themselves */
s_LBOSIPCacheTest(const string & host,const string & expected_result="N/A")3412 static void s_LBOSIPCacheTest(const string& host,
3413 const string& expected_result = "N/A")
3414 {
3415 CLBOSStatus lbos_status(true, true);
3416 string lbos_answer;
3417 string node_name = s_GenerateNodeName();
3418 unsigned short port = kDefaultPort;
3419 WRITE_LOG("Testing Resolve with host " << host <<
3420 ", expected result: " << expected_result);
3421 int count_before;
3422 SELECT_PORT(count_before, node_name, port);
3423
3424 string resolved_ip = CLBOSIpCache::HostnameResolve(node_name, host,
3425 "1.0.0", port);
3426 string IP = CLBOSIpCache::HostnameTryFind(node_name, host, "1.0.0", port);
3427
3428 NCBITEST_CHECK_EQUAL_MT_SAFE(resolved_ip, IP);
3429
3430 /* If result is predictable */
3431 if (expected_result != "N/A")
3432 NCBITEST_CHECK_EQUAL_MT_SAFE(expected_result, IP);
3433
3434 /* Cleanup */
3435 CLBOSIpCache::HostnameDelete(node_name, host, "1.0.0", port);
3436 }
3437
3438
3439 /** Resolve hostname that can be resolved to multiple options -
3440 * the resolved IP gets saved and then is returned again and again for
3441 * the same service name, version and port
3442 * @attention
3443 * No multithread, test uses private methods that are not thread-safe by
3444 * themselves */
ResolveHost__TryFindReturnsIP()3445 void ResolveHost__TryFindReturnsIP()
3446 {
3447 s_LBOSIPCacheTest("cnn.com");
3448 }
3449
3450
3451 /** Resolve and cache an IP address - it must be resolved to itself
3452 * @attention
3453 * No multithread, test uses private methods that are not thread-safe by
3454 * themselves */
ResolveIP__TryFindReturnsIP()3455 void ResolveIP__TryFindReturnsIP()
3456 {
3457 s_LBOSIPCacheTest("130.14.25.27", "130.14.25.27");
3458 }
3459
3460
3461 /** Resolve an empty string - get "Unknown error".
3462 * @attention
3463 * No multithread, test uses private methods that are not thread-safe by
3464 * themselves */
ResolveEmpty__Error()3465 void ResolveEmpty__Error()
3466 {
3467 ExceptionComparator<CLBOSException::eUnknown, 400>
3468 comparator("Internal error in LBOS Client IP Cache. "
3469 "Please contact developer\n");
3470 BOOST_CHECK_EXCEPTION(s_LBOSIPCacheTest("", s_GetMyIP()),
3471 CLBOSException, comparator);
3472 }
3473
3474
3475 /** Actually, this behavior is not used anywhere, but this is the contract,
3476 * and must be tested so it works if ever needed
3477 * @attention
3478 * No multithread, test uses private methods that are not thread-safe by
3479 * themselves */
Resolve0000__Return0000()3480 void Resolve0000__Return0000()
3481 {
3482 s_LBOSIPCacheTest("0.0.0.0", "0.0.0.0");
3483 }
3484
3485
3486 /** Real-life test. Announce a host and deannounce it: cache MUST forget
3487 * deannounced host
3488 * @attention
3489 * No multithread, test uses private methods that are not thread-safe by
3490 * themselves */
DeannounceHost__TryFindDoesNotFind()3491 void DeannounceHost__TryFindDoesNotFind()
3492 {
3493 string host = s_GetMyHost();
3494 CLBOSStatus lbos_status(true, true);
3495 string lbos_answer;
3496 string node_name = s_GenerateNodeName();
3497 unsigned short port = kDefaultPort;
3498 WRITE_LOG("Announce host - resolving works and saves resolution result");
3499 /* Prepare for test. We need to be sure that there is no previously
3500 * registered non-deleted service. We count server with chosen port
3501 * and check if there is no server already announced */
3502 int count_before;
3503 SELECT_PORT(count_before, node_name, port);
3504
3505 /* Pre-cleanup */
3506 CLBOSIpCache::HostnameDelete(node_name, host, "1.0.0", port);
3507
3508 /* Test - announce, then check TryFind */
3509 BOOST_CHECK_NO_THROW(s_AnnounceCPPSafe(node_name, "1.0.0", host,
3510 port, string("http://") + "iebdev11"
3511 ":" + s_PortStr(PORT_N) + "/health"));
3512 /* Deannounce */
3513 BOOST_CHECK_NO_THROW(s_DeannounceCPP(node_name, "1.0.0", host,
3514 port));
3515
3516 /* Check after deannounce */
3517 string IP = CLBOSIpCache::HostnameTryFind(node_name,
3518 host, "1.0.0", port);
3519 NCBITEST_CHECK_EQUAL_MT_SAFE(host, IP);
3520 }
3521
3522
3523 /** Test that for the second time rsolution result is taken from cache. Tested
3524 * with google.com which is very often resolved to different IPs
3525 * @attention
3526 * No multithread, test uses private methods that are not thread-safe by
3527 * themselves */
ResolveTwice__SecondTimeNoOp()3528 void ResolveTwice__SecondTimeNoOp()
3529 {
3530 string host = "google.com";
3531 CLBOSStatus lbos_status(true, true);
3532 string lbos_answer;
3533 string node_name = s_GenerateNodeName();
3534 unsigned short port = kDefaultPort;
3535 WRITE_LOG("Resolving the same name twice - on the second run function "
3536 "should return already saved result");
3537 int count_before;
3538 SELECT_PORT(count_before, node_name, port);
3539 string resolved_ip = CLBOSIpCache::HostnameResolve(node_name, host,
3540 "1.0.0", port);
3541 int i;
3542 stringstream sstream;
3543 string IP;
3544 BOOST_CHECK_NO_THROW(
3545 for (i = 0; i < 100; i++) {
3546 IP = CLBOSIpCache::HostnameResolve(node_name, host,
3547 "1.0.0", port);
3548 if (resolved_ip != IP)
3549 break;
3550 }
3551 );
3552 sstream << "Resolve does return consistent answers (iteration " << i << ")";
3553 NCBITEST_CHECK_MESSAGE_MT_SAFE(resolved_ip == IP, sstream.str().c_str());
3554 /* Cleanup */
3555 CLBOSIpCache::HostnameDelete(node_name, host, "1.0.0", port);
3556 }
3557
3558
3559 /** Add host to cache and then remove it multiple times - no crashes should
3560 * happen. The value MUST be deleted and not found.
3561 * @attention
3562 * No multithread, test uses private methods that are not thread-safe by
3563 * themselves */
DeleteTwice__SecondTimeNoOp()3564 void DeleteTwice__SecondTimeNoOp()
3565 {
3566 string host = s_GetMyHost();
3567 CLBOSStatus lbos_status(true, true);
3568 string lbos_answer;
3569 string node_name = s_GenerateNodeName();
3570 unsigned short port = kDefaultPort;
3571 WRITE_LOG("Resolving the same name twice - on the second run function "
3572 "should return already saved result");
3573 int count_before;
3574 SELECT_PORT(count_before, node_name, port);
3575 string resolved_ip = CLBOSIpCache::HostnameResolve(node_name, host,
3576 "1.0.0", port);
3577 int i;
3578 stringstream sstream;
3579 string IP;
3580 BOOST_CHECK_NO_THROW(
3581 for (i = 0; i < 100; i++) {
3582 CLBOSIpCache::HostnameDelete(node_name, host, "1.0.0", port);
3583 IP = CLBOSIpCache::HostnameTryFind(node_name, host,
3584 "1.0.0", port);
3585 if (s_GetMyHost() != IP)
3586 break;
3587 }
3588 );
3589 sstream << "IP is stored in the cache even after it was deleted" <<
3590 "(iteration " << i << ")";
3591 string my_host = s_GetMyHost();
3592 NCBITEST_CHECK_MESSAGE_MT_SAFE(my_host == IP, sstream.str().c_str());
3593 }
3594
3595
3596 /** Finding a resolved hostname multiple times - just a stress test that can
3597 * show leaking memory
3598 * @attention
3599 * No multithread, test uses private methods that are not thread-safe by
3600 * themselves */
TryFindTwice__SecondTimeNoOp()3601 void TryFindTwice__SecondTimeNoOp()
3602 {
3603 string host = "google.com";
3604 CLBOSStatus lbos_status(true, true);
3605 string lbos_answer;
3606 string node_name = s_GenerateNodeName();
3607 unsigned short port = kDefaultPort;
3608 WRITE_LOG("Resolving the same name twice - on the second run function "
3609 "should return already saved result");
3610 int count_before;
3611 SELECT_PORT(count_before, node_name, port);
3612 string resolved_ip = CLBOSIpCache::HostnameResolve(node_name, host,
3613 "1.0.0", port);
3614 int i;
3615 stringstream sstream;
3616 string IP;
3617 BOOST_CHECK_NO_THROW(
3618 for (i = 0; i < 100; i++) {
3619 IP = CLBOSIpCache::HostnameTryFind(node_name, host,
3620 "1.0.0", port);
3621 if (resolved_ip != IP)
3622 break;
3623 }
3624 );
3625 sstream << "TryFind does not return consistent answers (iteration " << i
3626 << "), original value: " << resolved_ip << ", outlying value: "
3627 << IP;
3628 NCBITEST_CHECK_MESSAGE_MT_SAFE(resolved_ip == IP, sstream.str().c_str());
3629 /* Cleanup */
3630 CLBOSIpCache::HostnameDelete(node_name, host, "1.0.0", port);
3631 }
3632
3633 } /* namespace IPCache */
3634
3635 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
3636 namespace ResetIterator
3637 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
3638 {
3639 void NoConditions__IterContainsZeroCandidates();
3640 void MultipleReset__ShouldNotCrash();
3641 void Multiple_AfterGetNextInfo__ShouldNotCrash();
3642 /*
3643 * Unit tested: SERV_Reset
3644 * Conditions: No Conditions
3645 * Expected result: iter contains zero Candidates
3646 */
NoConditions__IterContainsZeroCandidates()3647 void NoConditions__IterContainsZeroCandidates()
3648 {
3649 CLBOSStatus lbos_status(true, true);
3650 string service = "/lbos";
3651 CConnNetInfo net_info;
3652 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
3653 SERV_LOCALHOST, 0, 0.0,
3654 *net_info, 0, 0, 0, 0, 0));
3655 /*
3656 * We know that iter is LBOS's.
3657 */
3658 SERV_Reset(*iter);
3659 if (*iter == NULL) {
3660 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter != NULL,
3661 ": LBOS not found when should be");
3662 return;
3663 }
3664 SLBOS_Data* data = static_cast<SLBOS_Data*>(iter->data);
3665 NCBITEST_CHECK_MESSAGE_MT_SAFE(data->n_cand == 0,
3666 "Reset did not set n_cand to 0");
3667 NCBITEST_CHECK_MESSAGE_MT_SAFE(data->pos_cand == 0,
3668 "Reset did not set pos_cand "
3669 "to 0");
3670 }
3671
3672
3673 /*
3674 * Unit being tested: SERV_Reset
3675 * Conditions: Multiple reset
3676 * Expected result: should not crash
3677 */
MultipleReset__ShouldNotCrash()3678 void MultipleReset__ShouldNotCrash()
3679 {
3680 CLBOSStatus lbos_status(true, true);
3681 string service = "/lbos";
3682 SLBOS_Data* data;
3683 CConnNetInfo net_info;
3684 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
3685 SERV_LOCALHOST, 0, 0.0,
3686 *net_info, 0, 0, 0, 0, 0));
3687 /*
3688 * We know that iter is LBOS's. It must have clear info by
3689 * implementation before GetNextInfo is called, so we can set
3690 * source of LBOS address now
3691 */
3692 if (*iter == NULL) {
3693 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter != NULL, "LBOS not found when should be");
3694 return;
3695 }
3696 int i = 0;
3697 for (i = 0; i < 15; ++i) {
3698 /* If just don't crash here, it is good enough. No assert is
3699 * necessary, plus this will cause valgrind to swear if not all iter
3700 * is reset
3701 */
3702 SERV_Reset(*iter);
3703 if (*iter == NULL)
3704 continue;//If nothing found, and reset does not crash - good enough
3705 data = static_cast<SLBOS_Data*>(iter->data);
3706 NCBITEST_CHECK_EQUAL_MT_SAFE(data->n_cand, 0U);
3707 NCBITEST_CHECK_EQUAL_MT_SAFE(data->pos_cand, 0U);
3708 }
3709 return;
3710 }
3711
3712
Multiple_AfterGetNextInfo__ShouldNotCrash()3713 void Multiple_AfterGetNextInfo__ShouldNotCrash()
3714 {
3715 CLBOSStatus lbos_status(true, true);
3716 string service = "/lbos";
3717 SLBOS_Data* data;
3718 CConnNetInfo net_info;
3719 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
3720 SERV_LOCALHOST, 0, 0.0,
3721 *net_info, 0, 0, 0, 0, 0));
3722 if (*iter == NULL) {
3723 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter != NULL,
3724 "LBOS not found when should be");
3725 return;
3726 }
3727 /*
3728 * We know that iter is LBOS's. It must have clear info by implementation
3729 * before GetNextInfo is called, so we can set source of LBOS address now
3730 */
3731 int i = 0;
3732 for (i = 0; i < 15; ++i) {
3733 /* If just don't crash here, it is good enough. No assert is
3734 * necessary, plus this will cause valgrind to swear if not all iter
3735 * is reset
3736 */
3737 SERV_Reset(*iter);
3738 if (*iter == NULL)
3739 continue;//If nothing found, and reset does not crash - good enough
3740 data = static_cast<SLBOS_Data*>(iter->data);
3741 NCBITEST_CHECK_MESSAGE_MT_SAFE(data->n_cand == 0,
3742 "Reset did not set n_cand to 0");
3743 NCBITEST_CHECK_MESSAGE_MT_SAFE(data->pos_cand == 0,
3744 "Reset did not set pos_cand "
3745 "to 0");
3746
3747 HOST_INFO host_info; // we leave garbage here for a reason
3748 SERV_GetNextInfoEx(*iter, &host_info);
3749 data = static_cast<SLBOS_Data*>(iter->data);
3750 NCBITEST_CHECK_MESSAGE_MT_SAFE(data->n_cand > 0,
3751 "n_cand should be more than 0 after "
3752 "GetNextInfo");
3753 NCBITEST_CHECK_MESSAGE_MT_SAFE(data->pos_cand > 0,
3754 "pos_cand should be more than 0 after "
3755 "GetNextInfo");
3756 if (iter->op == NULL) {
3757 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op != NULL,
3758 "Mapper returned NULL when it should "
3759 "return s_op");
3760 return;
3761 }
3762 NCBITEST_CHECK_MESSAGE_MT_SAFE(strcmp(iter->op->mapper, "lbos") == 0,
3763 "Name of mapper that returned answer "
3764 "is not \"lbos\"");
3765 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op->Close != NULL,
3766 "Close operation pointer "
3767 "is null");
3768 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op->Feedback != NULL,
3769 "Feedback operation pointer is null");
3770 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op->GetNextInfo != NULL,
3771 "GetNextInfo operation pointer is null");
3772 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op->Reset != NULL,
3773 "Reset operation pointer is null");
3774 NCBITEST_CHECK_MESSAGE_MT_SAFE(host_info == NULL,
3775 "GetNextInfoEx did write something to "
3776 "host_info, when it should not");
3777 }
3778 return;
3779 }
3780 } /* namespace ResetIterator */
3781
3782
3783 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
3784 namespace CloseIterator
3785 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
3786 {
3787 void AfterOpen__ShouldWork();
3788 void AfterReset__ShouldWork();
3789 void AfterGetNextInfo__ShouldWork();
3790 void FullCycle__ShouldWork();
3791
AfterOpen__ShouldWork()3792 void AfterOpen__ShouldWork()
3793 {
3794 CLBOSStatus lbos_status(true, true);
3795 string service = "/lbos";
3796 CConnNetInfo net_info;
3797 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
3798 SERV_LOCALHOST, 0, 0.0,
3799 *net_info, 0, 0, 0, 0, 0));
3800 if (*iter == NULL) {
3801 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter != NULL,
3802 "LBOS not found when it should be");
3803 return;
3804 }
3805 /*
3806 * We know that iter is LBOS's.
3807 */
3808 /*SERV_Close(*iter);
3809 return;*/
3810 }
AfterReset__ShouldWork()3811 void AfterReset__ShouldWork()
3812 {
3813 CLBOSStatus lbos_status(true, true);
3814 string service = "/lbos";
3815 CConnNetInfo net_info;
3816 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
3817 SERV_LOCALHOST, 0, 0.0,
3818 *net_info, 0, 0, 0, 0, 0));
3819 if (*iter == NULL) {
3820 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter != NULL,
3821 "LBOS not found when it should be");
3822 return;
3823 }
3824 /*
3825 * We know that iter is LBOS's.
3826 */
3827 /*SERV_Reset(*iter);
3828 SERV_Close(*iter);*/
3829 }
3830
AfterGetNextInfo__ShouldWork()3831 void AfterGetNextInfo__ShouldWork()
3832 {
3833 CLBOSStatus lbos_status(true, true);
3834 string service = "/lbos";
3835 SLBOS_Data* data;
3836 CConnNetInfo net_info;
3837 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
3838 SERV_LOCALHOST, 0, 0.0,
3839 *net_info, 0, 0, 0, 0, 0));
3840 SERV_GetNextInfo(*iter);
3841 if (*iter == NULL) {
3842 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter != NULL,
3843 "LBOS not found when it should be");
3844 return;
3845 }
3846 /*
3847 * We know that iter is LBOS's.
3848 */
3849 data = static_cast<SLBOS_Data*>(iter->data);
3850 NCBITEST_CHECK_MESSAGE_MT_SAFE(data->n_cand > 0, "n_cand should be more than 0"
3851 " after GetNextInfo");
3852 NCBITEST_CHECK_MESSAGE_MT_SAFE(data->pos_cand > 0, "pos_cand should be more "
3853 "than 0 after GetNextInfo");
3854 }
3855
FullCycle__ShouldWork()3856 void FullCycle__ShouldWork()
3857 {
3858 CLBOSStatus lbos_status(true, true);
3859 string service = "/lbostest";
3860 SLBOS_Data* data;
3861 size_t i;
3862 CConnNetInfo net_info;
3863 /*
3864 * 0. We have to announce what we will be iterating through
3865 */
3866 unsigned short port1, port2, port3;
3867 int count_before;
3868 CCObjHolder<char> lbos_answer(NULL);
3869 /* Prepare for test. We need to be sure that there is no previously
3870 * registered non-deleted service. We count servers with chosen port
3871 * and check if there is no server already announced */
3872 lbos_answer = NULL;
3873 SELECT_PORT(count_before, service, port1);
3874 s_AnnounceCSafe(service.c_str(), "1.0.0", "", port1,
3875 (string("http://") + ANNOUNCEMENT_HOST + ":"
3876 + s_PortStr(PORT_N) + "/health").c_str(), "",
3877 &lbos_answer.Get(), NULL);
3878 lbos_answer = NULL;
3879
3880 SELECT_PORT(count_before, service, port2);
3881 s_AnnounceCSafe(service.c_str(), "1.0.0", "", port2,
3882 (string("http://") + ANNOUNCEMENT_HOST + ":"
3883 + s_PortStr(PORT_N) + "/health").c_str(), "",
3884 &lbos_answer.Get(), NULL);
3885 lbos_answer = NULL;
3886
3887 SELECT_PORT(count_before, service, port3);
3888 s_AnnounceCSafe(service.c_str(), "1.0.0", "", port3,
3889 (string("http://") + ANNOUNCEMENT_HOST + ":"
3890 + s_PortStr(PORT_N) + "/health").c_str(), "",
3891 &lbos_answer.Get(), NULL);
3892 lbos_answer = NULL;
3893
3894 unsigned int servers_found1 =
3895 s_CountServersWithExpectation(service, port1, 1, __LINE__,
3896 kDiscoveryDelaySec),
3897 servers_found2 =
3898 s_CountServersWithExpectation(service, port2, 1, __LINE__,
3899 kDiscoveryDelaySec),
3900 servers_found3 =
3901 s_CountServersWithExpectation(service, port3, 1, __LINE__,
3902 kDiscoveryDelaySec);
3903 NCBITEST_REQUIRE_MESSAGE_MT_SAFE(servers_found1 == 1, "lbostest was announced, "
3904 "but cannot find it");
3905 NCBITEST_REQUIRE_MESSAGE_MT_SAFE(servers_found2 == 1, "lbostest was announced, "
3906 "but cannot find it");
3907 NCBITEST_REQUIRE_MESSAGE_MT_SAFE(servers_found3 == 1, "lbostest was announced, "
3908 "but cannot find it");
3909 /*
3910 * 1. We close after first GetNextInfo
3911 */
3912 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
3913 SERV_LOCALHOST, 0, 0.0,
3914 *net_info, 0, 0, 0, 0, 0));
3915 NCBITEST_REQUIRE_MESSAGE_MT_SAFE(*iter != NULL,
3916 "Could not find announced lbostest nodes");
3917 SERV_GetNextInfo(*iter);
3918 data = static_cast<SLBOS_Data*>(iter->data);
3919 NCBITEST_CHECK_MESSAGE_MT_SAFE(data->n_cand > 0, "n_cand should be more than 0"
3920 " after GetNextInfo");
3921 NCBITEST_CHECK_MESSAGE_MT_SAFE(data->pos_cand > 0, "pos_cand should be more "
3922 "than 0 after GetNextInfo");
3923
3924 /*
3925 * 2. We close after half hosts checked with GetNextInfo
3926 */
3927 iter = s_SERVOpenP_Safe(service.c_str(), fSERV_All,
3928 SERV_LOCALHOST, 0, 0.0,
3929 *net_info, 0, 0, 0, 0, 0);
3930 if (*iter == NULL) {
3931 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter != NULL,
3932 "Could not find announced "
3933 "lbostest nodes");
3934 return;
3935 }
3936 data = static_cast<SLBOS_Data*>(iter->data);
3937 /* v half */
3938 for (i = 0; i < static_cast<SLBOS_Data*>(iter->data)->n_cand / 2; ++i) {
3939 SERV_GetNextInfo(*iter);
3940 }
3941 NCBITEST_CHECK_MESSAGE_MT_SAFE(data->n_cand > 0, "n_cand should be more than 0"
3942 " after GetNextInfo");
3943 NCBITEST_CHECK_MESSAGE_MT_SAFE(data->pos_cand > 0, "pos_cand should be more "
3944 "than 0 after GetNextInfo");
3945
3946 /* 3. We close after all hosts checked with GetNextInfo*/
3947 iter = s_SERVOpenP_Safe(service.c_str(), fSERV_All,
3948 SERV_LOCALHOST, 0, 0.0,
3949 *net_info, 0, 0, 0, 0, 0);
3950
3951 if (*iter == NULL) {
3952 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter != NULL,
3953 "Could not find announced lbostest nodes");
3954 return;
3955 }
3956 for (i = 0; i < static_cast<SLBOS_Data*>(iter->data)->n_cand; ++i) {
3957 SERV_GetNextInfo(*iter);
3958 }
3959 data = static_cast<SLBOS_Data*>(iter->data);
3960 NCBITEST_CHECK_MESSAGE_MT_SAFE(data->n_cand > 0, "n_cand should be more than 0"
3961 " after GetNextInfo");
3962 NCBITEST_CHECK_MESSAGE_MT_SAFE(data->pos_cand > 0, "pos_cand should be more "
3963 "than 0 after GetNextInfo");
3964
3965 /* Cleanup */
3966 s_DeannounceC(service.c_str(), "1.0.0", "", port1,
3967 &lbos_answer.Get(), NULL);
3968 s_DeannounceC(service.c_str(), "1.0.0", "", port2,
3969 &lbos_answer.Get(), NULL);
3970 s_DeannounceC(service.c_str(), "1.0.0", "", port3,
3971 &lbos_answer.Get(), NULL);
3972
3973 lbos_answer = NULL;
3974 }
3975
3976
3977 } /* namespace CloseIterator */
3978
3979
3980 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
3981 namespace DTab
3982 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
3983 {
3984 /* 1. Mix of registry DTab and HTTP Dtab: registry goes first */
DTabRegistryAndHttp__RegistryGoesFirst()3985 void DTabRegistryAndHttp__RegistryGoesFirst()
3986 {
3987 CLBOSStatus lbos_status(true, true);
3988 string service = "/lbos";
3989 CConnNetInfo net_info;
3990 CMockFunction<FLBOS_ConnReadMethod*> mock(
3991 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
3992 s_FakeReadWithErrorFromLBOSCheckDTab);
3993 ConnNetInfo_SetUserHeader(*net_info,
3994 "DTab-local: /lbostest=>/zk#/lbostest/1.1.0");
3995 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
3996 SERV_LOCALHOST, 0, 0.0,
3997 *net_info, 0, 0, 0, 0, 0));
3998 string expected_header = "DTab-local: /lbostest=>/zk#/lbostest/1.0.0; "
3999 "/lbostest=>/zk#/lbostest/1.1.0";
4000
4001 NCBITEST_CHECK_MESSAGE_MT_SAFE(s_LBOS_header.substr(
4002 0, expected_header.length()) ==
4003 expected_header,
4004 "Header with DTab did not combine "
4005 "as expected");
4006 }
4007
4008 /** 2. Announce server with non-standard version and server with no standard
4009 version at all. Both should be found via DTab */
NonStandardVersion__FoundWithDTab()4010 void NonStandardVersion__FoundWithDTab()
4011 {
4012 CLBOSStatus lbos_status(true, true);
4013 string service = "/lbostest";
4014 CConnNetInfo net_info;
4015 CCObjHolder<char> lbos_answer(NULL);
4016 unsigned short port = s_GeneratePort();
4017 /*
4018 * I. Non-standard version
4019 */
4020 int count_before =
4021 s_CountServers(service, port,
4022 "DTab-local: /lbostest=>/zk#/lbostest/1.1.0");
4023 while (count_before != 0) {
4024 port = s_GeneratePort();
4025 count_before =
4026 s_CountServers(service, port,
4027 "DTab-local: /lbostest=>/zk#/lbostest/1.1.0");
4028 }
4029
4030 s_AnnounceCSafe(service.c_str(), "1.1.0", "", port,
4031 (string("http://") + ANNOUNCEMENT_HOST + ":" +
4032 s_PortStr(PORT_N) + "/health").c_str(), "",
4033 &lbos_answer.Get(), NULL);
4034
4035 unsigned int servers_found =
4036 s_CountServersWithExpectation(service, port, 1, __LINE__,
4037 kDiscoveryDelaySec, "DTab-local: "
4038 "/lbostest=>/zk#/lbostest/1.1.0");
4039 NCBITEST_CHECK_MESSAGE_MT_SAFE(servers_found == 1,
4040 "Error while searching non-standard server "
4041 "version with DTab");
4042 /* Cleanup */
4043 s_DeannounceC(service.c_str(), "1.1.0", NULL, port, NULL, NULL);
4044 lbos_answer = NULL;
4045
4046 /*
4047 * II. Service with no standard version in ZK config
4048 */
4049 service = "/lbostest1";
4050 count_before = s_CountServers(service, port,
4051 "DTab-local: /lbostest1=>/zk#/"
4052 "lbostest1/1.1.0");
4053 while (count_before != 0) {
4054 port = s_GeneratePort();
4055 count_before =
4056 s_CountServers(service, port,
4057 "DTab-local: /lbostest1=>/zk#/lbostest1/1.1.0");
4058 }
4059 s_AnnounceCSafe(service.c_str(), "1.1.0", "", port,
4060 ("http://" ANNOUNCEMENT_HOST_0000 ":" + s_PortStr(PORT_N) +
4061 "/health").c_str(), "",
4062 &lbos_answer.Get(), NULL);
4063 servers_found =
4064 s_CountServersWithExpectation(service, port, 1, __LINE__,
4065 kDiscoveryDelaySec, "DTab-local: "
4066 "/lbostest1=>/zk#/lbostest1/1.1.0");
4067 NCBITEST_CHECK_MESSAGE_MT_SAFE(servers_found == 1,
4068 "Error while searching server with no "
4069 "standard version with DTab");
4070
4071 /* Cleanup */
4072 s_DeannounceC(service.c_str(), "1.1.0", NULL, port, NULL, NULL);
4073 lbos_answer = NULL;
4074 }
4075
4076 /* 3. Mix of registry DTab and HTTP Dtab and request Dtab: registry goes first,
4077 * then goes ConnNetInfo DTab, then goes RequestContext */
DTabRegistryAndHttpAndRequestContext__RegistryGoesFirst()4078 void DTabRegistryAndHttpAndRequestContext__RegistryGoesFirst()
4079 {
4080 CLBOSStatus lbos_status(true, true);
4081 string service = "/lbos";
4082 CConnNetInfo net_info;
4083 CMockFunction<FLBOS_ConnReadMethod*> mock(
4084 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
4085 s_FakeReadWithErrorFromLBOSCheckDTab);
4086 ConnNetInfo_SetUserHeader(*net_info,
4087 "DTab-local: /lbostest=>/zk#/lbostest/1.1.0");
4088 CDiagContext::GetRequestContext().SetDtab("DTab-local: /lbostest=>"
4089 "/zk#/lbostest/1.2.0");
4090 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
4091 SERV_LOCALHOST, 0, 0.0,
4092 *net_info, 0, 0, 0, 0, 0));
4093 string expected_header = "DTab-local: /lbostest=>/zk#/lbostest/1.0.0; "
4094 "/lbostest=>/zk#/lbostest/1.1.0 ; "
4095 "/lbostest=>/zk#/lbostest/1.2.0";
4096
4097 NCBITEST_CHECK_MESSAGE_MT_SAFE(s_LBOS_header.substr(0,
4098 expected_header.length()) == expected_header,
4099 "Header with DTab did not combine as "
4100 "expected");
4101 }
4102
4103 /** 4. Announce server with non-standard version and server with no standard
4104 version at all. Both should be found via Request Context DTab */
NonStandardVersion__FoundWithRequestContextDTab()4105 void NonStandardVersion__FoundWithRequestContextDTab()
4106 {
4107 CLBOSStatus lbos_status(true, true);
4108 string service = "/lbostest";
4109 CConnNetInfo net_info;
4110 CCObjHolder<char> lbos_answer(NULL);
4111 unsigned short port = s_GeneratePort();
4112 /*
4113 * I. Non-standard version
4114 */
4115 int count_before =
4116 s_CountServers(service, port,
4117 "DTab-local: /lbostest=>/zk#/lbostest/1.2.0");
4118 while (count_before != 0) {
4119 port = s_GeneratePort();
4120 count_before =
4121 s_CountServers(service, port,
4122 "DTab-local: /lbostest=>/zk#/lbostest/1.2.0");
4123 }
4124
4125 s_AnnounceCSafe(service.c_str(), "1.2.0", "", port,
4126 (string("http://") + ANNOUNCEMENT_HOST + ":" +
4127 s_PortStr(PORT_N) + "/health").c_str(), "",
4128 &lbos_answer.Get(), NULL);
4129
4130 CDiagContext::GetRequestContext().SetDtab("DTab-local: /lbostest=>"
4131 "/zk#/lbostest/1.2.0");
4132 unsigned int servers_found =
4133 s_CountServersWithExpectation(service, port, 1, __LINE__,
4134 kDiscoveryDelaySec, "DTab-local: "
4135 "/lbostest=>/zk#/lbostest/1.1.0");
4136 CDiagContext::GetRequestContext().SetDtab("");
4137 NCBITEST_CHECK_MESSAGE_MT_SAFE(servers_found == 1,
4138 "Error while searching non-standard server "
4139 "version with DTab");
4140 /* Cleanup */
4141 s_DeannounceC(service.c_str(), "1.2.0", NULL, port, NULL, NULL);
4142 lbos_answer = NULL;
4143
4144 /*
4145 * II. Service with no standard version in ZK config
4146 */
4147 service = "/lbostest1";
4148 count_before = s_CountServers(service, port,
4149 "DTab-local: /lbostest1=>/zk#/"
4150 "lbostest1/1.2.0");
4151 while (count_before != 0) {
4152 port = s_GeneratePort();
4153 count_before =
4154 s_CountServers(service, port,
4155 "DTab-local: /lbostest1=>/zk#/lbostest1/1.2.0");
4156 }
4157 s_AnnounceCSafe(service.c_str(), "1.2.0", "", port,
4158 "http://" ANNOUNCEMENT_HOST_0000 ":" +
4159 s_PortStr(PORT_N) + "/health", "",
4160 &lbos_answer.Get(), NULL);
4161
4162 CDiagContext::GetRequestContext().SetDtab("DTab-local: /lbostest1=>/zk#/"
4163 "lbostest1/1.2.0");
4164 servers_found =
4165 s_CountServersWithExpectation(service, port, 1, __LINE__,
4166 kDiscoveryDelaySec, "DTab-local: "
4167 "/lbostest1=>/zk#/lbostest1/1.1.0");
4168 CDiagContext::GetRequestContext().SetDtab("");
4169 NCBITEST_CHECK_MESSAGE_MT_SAFE(servers_found == 1,
4170 "Error while searching server with no standard"
4171 "version with DTab");
4172
4173 /* Cleanup */
4174 s_DeannounceC(service.c_str(), "1.2.0", NULL, port, NULL, NULL);
4175 lbos_answer = NULL;
4176 }
4177
4178
4179 } /* namespace DTab */
4180
4181
4182 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
4183 namespace ResolveViaLBOS
4184 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
4185 {
4186 void ServiceExists__ReturnHostIP();
4187 void LegacyService__ReturnHostIP();
4188 void ServiceDoesNotExist__ReturnNULL();
4189 void NoLBOS__ReturnNULL();
4190 void FakeMassiveInput__ShouldProcess();
4191 void FakeErrorInput__ShouldNotCrash();
4192
ServiceExists__ReturnHostIP()4193 void ServiceExists__ReturnHostIP()
4194 {
4195 string service = "/lbos";
4196 CConnNetInfo net_info;
4197 CCObjHolder<char> lbos_address(g_LBOS_GetLBOSAddress());
4198 string lbos_addr(lbos_address.Get());
4199 /*
4200 * We know that iter is LBOS's.
4201 */
4202 CCObjArrayHolder<SSERV_Info> hostports(
4203 g_LBOS_UnitTesting_GetLBOSFuncs()->ResolveIPPort(
4204 lbos_addr.c_str(),
4205 service.c_str(),
4206 *net_info));
4207 size_t i = 0;
4208 if (*hostports != NULL) {
4209 for (i = 0; hostports[i] != NULL; i++) {
4210 NCBITEST_CHECK_MESSAGE_MT_SAFE(hostports[i]->host > 0,
4211 "Problem with getting host for "
4212 "server");
4213 NCBITEST_CHECK_MESSAGE_MT_SAFE(hostports[i]->port > 0,
4214 "Problem with getting port for "
4215 "server");
4216 NCBITEST_CHECK_MESSAGE_MT_SAFE(hostports[i]->port < 65535,
4217 "Problem with getting port for "
4218 "server");
4219 }
4220 }
4221 NCBITEST_CHECK_MESSAGE_MT_SAFE(i > 0,
4222 "Problem with searching for service");
4223 }
4224
4225
4226 /** Look for accn2gi and check if a valid IP is returned */
LegacyService__ReturnHostIP()4227 void LegacyService__ReturnHostIP()
4228 {
4229 string service = "accn2gi";
4230 CConnNetInfo net_info;
4231 CCObjHolder<char> lbos_address(g_LBOS_GetLBOSAddress());
4232 string lbos_addr(lbos_address.Get());
4233 /* Announce the legacy service */
4234
4235 /*
4236 * We know that iter is LBOS's.
4237 */
4238 CCObjArrayHolder<SSERV_Info> hostports(
4239 g_LBOS_UnitTesting_GetLBOSFuncs()->ResolveIPPort(
4240 lbos_addr.c_str(),
4241 service.c_str(),
4242 *net_info));
4243 size_t i = 0;
4244 if (*hostports != NULL) {
4245 for (i = 0; hostports[i] != NULL; i++) {
4246 NCBITEST_CHECK_MESSAGE_MT_SAFE(hostports[i]->host > 0,
4247 "Problem with getting host for "
4248 "server");
4249 NCBITEST_CHECK_MESSAGE_MT_SAFE(hostports[i]->port > 0,
4250 "Problem with getting port for "
4251 "server");
4252 NCBITEST_CHECK_MESSAGE_MT_SAFE(hostports[i]->port < 65535,
4253 "Problem with getting port for "
4254 "server");
4255 }
4256 }
4257 NCBITEST_CHECK_MESSAGE_MT_SAFE(i > 0, "Problem with searching for service");
4258 }
4259
4260
ServiceDoesNotExist__ReturnNULL()4261 void ServiceDoesNotExist__ReturnNULL()
4262 {
4263 CLBOSStatus lbos_status(true, true);
4264 string service = "/service/doesnotexist";
4265 CConnNetInfo net_info;
4266 CCObjHolder<char> lbos_address(g_LBOS_GetLBOSAddress());
4267 string lbos_addr(lbos_address.Get());
4268 /*
4269 * We know that iter is LBOS's.
4270 */
4271 CCObjArrayHolder<SSERV_Info> hostports(
4272 g_LBOS_UnitTesting_GetLBOSFuncs()->ResolveIPPort(
4273 lbos_addr.c_str(),
4274 service.c_str(),
4275 *net_info));
4276 NCBITEST_CHECK_MESSAGE_MT_SAFE(hostports.count() == 0, "Mapper should not find "
4277 "service, but it somehow "
4278 "found.");
4279 }
4280
4281
NoLBOS__ReturnNULL()4282 void NoLBOS__ReturnNULL()
4283 {
4284 CLBOSStatus lbos_status(true, true);
4285 string service = "/lbos";
4286 CConnNetInfo net_info;
4287 /*
4288 * We know that iter is LBOS's.
4289 */
4290
4291 CCObjArrayHolder<SSERV_Info> hostports(
4292 g_LBOS_UnitTesting_GetLBOSFuncs()->ResolveIPPort(
4293 "lbosdevacvancbinlmnih.gov:80",
4294 service.c_str(),
4295 *net_info));
4296 NCBITEST_CHECK_MESSAGE_MT_SAFE(hostports.count() == 0,
4297 "Mapper should not find LBOS, but it somehow"
4298 "found.");
4299 }
4300
4301
4302 struct SHostCheck
4303 {
4304 unsigned int host;
4305 bool check;
4306 };
4307
4308
FakeMassiveInput__ShouldProcess()4309 void FakeMassiveInput__ShouldProcess()
4310 {
4311 CLBOSStatus lbos_status(true, true);
4312 string service = "/service/doesnotexist";
4313 unsigned int temp_ip;
4314 unsigned short temp_port;
4315 CCounterResetter resetter(s_CallCounter);
4316 CConnNetInfo net_info;
4317 /*
4318 * We know that iter is LBOS's.
4319 */
4320 CMockFunction<FLBOS_ConnReadMethod*> mock(
4321 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
4322 s_FakeReadDiscovery<200>);
4323 CCObjArrayHolder<SSERV_Info> hostports(
4324 g_LBOS_UnitTesting_GetLBOSFuncs()->ResolveIPPort(
4325 "lbosdevacvancbinlmnih.gov", "/lbos", *net_info));
4326 int i = 0;
4327 NCBITEST_CHECK_MESSAGE_MT_SAFE(*hostports != NULL,
4328 "Problem with fake massive input, "
4329 "no servers found. "
4330 "Most likely, problem with test.");
4331 ostringstream temp_host;
4332 map<unsigned short, SHostCheck> hosts;
4333 for (i = 0; i < 200; i++) {
4334 temp_host.str("");
4335 temp_host << i+1 << "." << i+2 << "." << i+3 << "." << i+4
4336 << ":" << (i+1)*215;
4337 SOCK_StringToHostPort(temp_host.str().c_str(),
4338 &temp_ip,
4339 &temp_port);
4340 hosts[temp_port] = SHostCheck{ temp_ip, false };
4341 }
4342 if (*hostports) {
4343 for (i = 0; hostports[i] != NULL; i++) {
4344 SHostCheck& host_check = hosts[hostports[i]->port];
4345 NCBITEST_CHECK_MESSAGE_MT_SAFE(
4346 host_check.host == hostports[i]->host,
4347 "Problem with recognizing port or IP in massive input");
4348 if (host_check.host == hostports[i]->host) {
4349 host_check.check = true;
4350 }
4351 }
4352 i = 0;
4353 auto iter = hosts.begin();
4354 for (; iter != hosts.end(); iter++) {
4355 if (iter->second.check)
4356 i++;
4357 }
4358 stringstream ss;
4359 ss << "Mapper should find 200 hosts, but found " << i;
4360 NCBITEST_CHECK_MESSAGE_MT_SAFE(i == 200, ss.str().c_str());
4361 }
4362 }
4363
4364
4365 /** Check that LBOS client shuffles input from LBOS. Check occurence of different
4366 * combinations when there are just 3 elements in array*/
FakeMassiveInput__ShouldShuffle()4367 void FakeMassiveInput__ShouldShuffle()
4368 {
4369 CLBOSStatus lbos_status(true, true);
4370 string service = "/service/doesnotexist";
4371 unsigned int temp_ip;
4372 CCounterResetter resetter(s_CallCounter);
4373 CConnNetInfo net_info;
4374 size_t n_retries = 30000;
4375 /*
4376 * We know that iter is LBOS's.
4377 */
4378 CMockFunction<FLBOS_ConnReadMethod*> mock(
4379 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
4380 s_FakeReadDiscovery<3>);
4381 CCObjArrayHolder<SSERV_Info> hostports(
4382 g_LBOS_UnitTesting_GetLBOSFuncs()->ResolveIPPort(
4383 "lbosdevacvancbinlmnih.gov", "/lbos", *net_info));
4384 NCBITEST_CHECK_MESSAGE_MT_SAFE(*hostports != NULL,
4385 "Problem with fake massive input, "
4386 "no servers found. "
4387 "Most likely, problem with test.");
4388 /* First, prepare examples for each group */
4389 unsigned short port1, port2, port3; /* we compare only ports, for speed */
4390 /* Combinations:
4391 * 1) 1, 2, 3
4392 * 2) 1, 3, 2
4393 * 3) 2, 1, 3
4394 * 4) 2, 3, 1
4395 * 5) 3, 1, 2
4396 * 6) 3, 2, 1
4397 */
4398 size_t n[6]; /* For 6 different combinations we count occurrence*/
4399 memset(n, 0, sizeof(n));
4400 SOCK_StringToHostPort("1.2.3.4:215", &temp_ip, &port1);
4401 SOCK_StringToHostPort("2.3.4.5:430", &temp_ip, &port2);
4402 SOCK_StringToHostPort("3.4.5.6:645", &temp_ip, &port3);
4403 /* we do 30 thousand retries */
4404 for ( size_t retries = 0; retries < n_retries; retries++ ) {
4405 hostports =
4406 g_LBOS_UnitTesting_GetLBOSFuncs()->ResolveIPPort(
4407 "lbosdevacvancbinlmnih.gov", "/lbos", *net_info);
4408 NCBITEST_CHECK_MESSAGE(*hostports != NULL, "ResolveIPPort return NULL "
4409 "instead of SSERV_Info array");
4410 if (hostports[0]->port == port1) {
4411 if (hostports[1]->port == port2) {
4412 n[0]++;
4413 } else if (hostports[1]->port == port3) {
4414 n[1]++;
4415 }
4416 } else if (hostports[0]->port == port2) {
4417 if (hostports[1]->port == port1) {
4418 n[2]++;
4419 } else if (hostports[1]->port == port3) {
4420 n[3]++;
4421 }
4422 } else if (hostports[0]->port == port3) {
4423 if (hostports[1]->port == port1) {
4424 n[4]++;
4425 } else if (hostports[1]->port == port2) {
4426 n[5]++;
4427 }
4428 }
4429 }
4430 /** Not any combination should occur more than with n_retries/50 deviation
4431 * from average (n_retries/6) */
4432 for (size_t j = 0; j < 6; j++) {
4433 ostringstream message;
4434 message << "Combination " << j << " has " << n[j] << " occurrences (too"
4435 " much deviation from average of " << n_retries / 6 << ")";
4436 NCBITEST_CHECK_MESSAGE(n[j] >= n_retries / 6 - n_retries / 50,
4437 message.str().c_str());
4438 NCBITEST_CHECK_MESSAGE(n[j] <= n_retries / 6 + n_retries / 50,
4439 message.str().c_str());
4440 }
4441 }
4442
4443
FakeErrorInput__ShouldNotCrash()4444 void FakeErrorInput__ShouldNotCrash()
4445 {
4446 CLBOSStatus lbos_status(true, true);
4447 string service = "/service/doesnotexist";
4448 unsigned int temp_ip;
4449 unsigned short temp_port;
4450 s_CallCounter = 0;
4451 CConnNetInfo net_info;
4452 /*
4453 * We know that iter is LBOS's.
4454 */
4455 CMockFunction<FLBOS_ConnReadMethod*> mock(
4456 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
4457 s_FakeReadDiscoveryCorrupt<200>);
4458 CCObjArrayHolder<SSERV_Info> hostports(
4459 g_LBOS_UnitTesting_GetLBOSFuncs()->ResolveIPPort(
4460 "lbosdevacvancbinlmnih.gov", "/lbos", *net_info));
4461 int i=0; /* iterate test numbers*/
4462 NCBITEST_CHECK_MESSAGE_MT_SAFE(*hostports != NULL,
4463 "Problem with fake error input, no servers found. "
4464 "Most likely, problem with test.");
4465 map<unsigned short, SHostCheck> hosts;
4466 for (i = 0; i < 200; i++) {
4467 stringstream ss;
4468 ss << 0 << i + 1 << "."
4469 << 0 << i + 2 << "."
4470 << 0 << i + 3 << "."
4471 << 0 << i + 4;
4472 if ( ss.str().find('8') != string::npos ||
4473 ss.str().find('9') != string::npos )
4474 {
4475 WRITE_LOG(ss.str() << " Has 8 or 9, skipping");
4476 continue;
4477 }
4478 ss << ":" << (i + 1) * 215;
4479 SOCK_StringToHostPort(ss.str().c_str(), &temp_ip, &temp_port);
4480 hosts[temp_port] = SHostCheck{ temp_ip, false };
4481 }
4482 if (*hostports) {
4483 for (i = 0; hostports[i] != NULL; i++) {
4484 SHostCheck& host_check = hosts[hostports[i]->port];
4485 NCBITEST_CHECK_MESSAGE_MT_SAFE(
4486 host_check.host == hostports[i]->host,
4487 "Problem with recognizing port or IP in massive input");
4488 if (host_check.host == hostports[i]->host) {
4489 host_check.check = true;
4490 }
4491 }
4492 i = 0;
4493 auto iter = hosts.begin();
4494 for (; iter != hosts.end(); iter++) {
4495 if (iter->second.check)
4496 i++;
4497 }
4498 stringstream ss;
4499 ss << "Mapper should find 80 hosts, but found " << i;
4500 NCBITEST_CHECK_MESSAGE_MT_SAFE(i == 80, ss.str().c_str());
4501 }
4502 }
4503 } /* namespace ResolveViaLBOS */
4504
4505 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
4506 namespace GetLBOSAddress
4507 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
4508 {
4509 void SpecificMethod__FirstInResult();
4510 void CustomHostNotProvided__SkipCustomHost();
4511 void NoConditions__AddressDefOrder();
4512
4513 /* Not thread-safe because of using s_LBOS_funcs */
SpecificMethod__FirstInResult()4514 void SpecificMethod__FirstInResult()
4515 {
4516 CLBOSStatus lbos_status(true, true);
4517 string custom_lbos = "lbos.custom.host";
4518 CCObjHolder<char> addresses(
4519 g_LBOS_GetLBOSAddressEx(eLBOS_FindMethod_CustomHost,
4520 custom_lbos.c_str()));
4521 /* I. Custom address */
4522 WRITE_LOG("Part 1. Testing custom LBOS address");
4523 NCBITEST_CHECK_EQUAL_MT_SAFE(string(addresses.Get()), custom_lbos);
4524
4525 /* II. Registry address */
4526 string registry_lbos =
4527 CNcbiApplication::Instance()->GetConfig().Get("CONN", "LBOS");
4528 WRITE_LOG("Part 2. Testing registry LBOS address");
4529 addresses = g_LBOS_GetLBOSAddressEx(eLBOS_FindMethod_Registry, NULL);
4530 NCBITEST_CHECK_EQUAL_MT_SAFE(string(addresses.Get()), registry_lbos);
4531
4532 /* We have to fake last method, because its result is dependent on
4533 * location */
4534 /* III. etc/ncbi address (should be 127.0.0.1) */
4535 #if defined NCBI_OS_LINUX || defined NCBI_OS_MSWIN
4536 WRITE_LOG("Part 3. Testing " LBOSRESOLVER_PATH);
4537 size_t buffer_size = 1024;
4538 size_t size;
4539 AutoArray<char> buffer(new char[buffer_size]);
4540 AutoPtr<IReader> reader(CFileReader::New(LBOSRESOLVER_PATH));
4541 ERW_Result result = reader->Read(buffer.get(), buffer_size, &size);
4542 NCBITEST_REQUIRE_MESSAGE_MT_SAFE(result == eRW_Success, "Could not read "
4543 LBOSRESOLVER_PATH ", test failed");
4544 buffer.get()[size] = '\0';
4545 string lbosresolver(buffer.get() + 7);
4546 lbosresolver = NStr::Replace(lbosresolver, "\n", "");
4547 lbosresolver = NStr::Replace(lbosresolver, "\r", "");
4548 lbosresolver = lbosresolver.erase(lbosresolver.length() - 5);
4549 addresses = g_LBOS_GetLBOSAddressEx(eLBOS_FindMethod_Lbosresolve, NULL);
4550 NCBITEST_CHECK_EQUAL_MT_SAFE(string(addresses.Get()), lbosresolver);
4551 #endif /* defined NCBI_OS_LINUX || defined NCBI_OS_MSWIN */
4552 }
4553
CustomHostNotProvided__SkipCustomHost()4554 void CustomHostNotProvided__SkipCustomHost()
4555 {
4556 CLBOSStatus lbos_status(true, true);
4557 CCObjHolder<char> addresses(
4558 g_LBOS_GetLBOSAddressEx(eLBOS_FindMethod_CustomHost,
4559 NULL));
4560 /* We check the count of LBOS addresses */
4561 NCBITEST_CHECK_MESSAGE_MT_SAFE(addresses.Get() != NULL,
4562 "Custom host was not processed in "
4563 "g_LBOS_GetLBOSAddressEx");
4564 }
4565
NoConditions__AddressDefOrder()4566 void NoConditions__AddressDefOrder()
4567 {
4568 CNcbiRegistry& registry = CNcbiApplication::Instance()->GetConfig();
4569 string lbos = registry.Get("CONN", "lbos");
4570 /* I. Registry has entry (we suppose that it has by default) */
4571 CCObjHolder<char> addresses(g_LBOS_GetLBOSAddress());
4572 WRITE_LOG("1. Checking LBOS address when registry LBOS is provided");
4573 NCBITEST_CHECK_EQUAL_MT_SAFE(string(addresses.Get()), lbos);
4574
4575 /* II. Registry has no entries - check that LBOS is read from
4576 * LBOSRESOLVER_PATH */
4577 #if defined NCBI_OS_LINUX || defined NCBI_OS_MSWIN
4578 WRITE_LOG("2. Checking LBOS address when registry LBOS is not provided");
4579 size_t buffer_size = 1024;
4580 size_t size;
4581 AutoArray<char> buffer(new char[buffer_size]);
4582 AutoPtr<IReader> reader(CFileReader::New(LBOSRESOLVER_PATH));
4583 ERW_Result result = reader->Read(buffer.get(), buffer_size, &size);
4584 NCBITEST_REQUIRE_MESSAGE_MT_SAFE(result == eRW_Success, "Could not read "
4585 LBOSRESOLVER_PATH ", test failed");
4586 buffer.get()[size] = '\0';
4587 string lbosresolver(buffer.get() + 7);
4588 lbosresolver = NStr::Replace(lbosresolver, "\n", "");
4589 lbosresolver = NStr::Replace(lbosresolver, "\r", "");
4590 lbosresolver = lbosresolver.erase(lbosresolver.length()-5);
4591 registry.Unset("CONN", "lbos");
4592 addresses = g_LBOS_GetLBOSAddress();
4593 NCBITEST_CHECK_EQUAL_MT_SAFE(string(addresses.Get()), lbosresolver);
4594 #endif /* defined NCBI_OS_LINUX || defined NCBI_OS_MSWIN */
4595
4596 /* Cleanup */
4597 registry.Set("CONN", "lbos", lbos);
4598 }
4599 } /* namespace GetLBOSAddress */
4600
4601
4602 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
4603 namespace GetCandidates
4604 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
4605 {
LBOSNoResponse__ErrorNoLBOS()4606 void LBOSNoResponse__ErrorNoLBOS()
4607 {
4608 CLBOSStatus lbos_status(true, true);
4609 string service = "/lbos";
4610 CCounterResetter resetter(s_CallCounter);
4611 CConnNetInfo net_info;
4612 CCObjHolder<char> lbos_address(g_LBOS_GetLBOSAddress());
4613 string lbos_addr(lbos_address.Get());
4614 CMockFunction<FLBOS_ResolveIPPortMethod*> mock(
4615 g_LBOS_UnitTesting_GetLBOSFuncs()->ResolveIPPort,
4616 s_FakeResolveIPPort);
4617
4618 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
4619 SERV_LOCALHOST, 0, 0.0,
4620 *net_info, 0, 0, 0, 0, 0, 0));
4621 NCBITEST_REQUIRE_MESSAGE_MT_SAFE(*iter == NULL,
4622 "LBOS found when it should not be");
4623 }
4624
LBOSResponds__Finish()4625 void LBOSResponds__Finish()
4626 {
4627 CLBOSStatus lbos_status(true, true);
4628 CCounterResetter resetter(s_CallCounter);
4629 string service = "/lbos";
4630 CConnNetInfo net_info;
4631 CCObjHolder<char> lbos_address(g_LBOS_GetLBOSAddress());
4632 string lbos_addr(lbos_address.Get());
4633 s_CallCounter = 2;
4634 CMockFunction<FLBOS_ResolveIPPortMethod*> mock(
4635 g_LBOS_UnitTesting_GetLBOSFuncs()->ResolveIPPort,
4636 s_FakeResolveIPPort);
4637
4638 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
4639 SERV_LOCALHOST, 0, 0.0,
4640 *net_info, 0, 0, 0, 0, 0));
4641 if (*iter == NULL) {
4642 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter != NULL,
4643 "LBOS not found when it should be");
4644 return;
4645 }
4646 static_cast<SLBOS_Data*>(iter->data)->lbos_addr = lbos_addr.c_str();
4647 HOST_INFO hinfo;
4648 SERV_GetNextInfoEx(*iter, &hinfo);
4649
4650 /* We do not care about results, we care how many IPs algorithm tried
4651 * to resolve service. We expect only one call, which means that counter
4652 * should increase by 1
4653 */
4654 NCBITEST_CHECK_MESSAGE_MT_SAFE(s_CallCounter == 3,
4655 "s_LBOS_FillCandidates: Incorrect "
4656 "processing of alive LBOS");
4657 }
4658
4659 /*Not thread safe because of s_LastHeader*/
NetInfoProvided__UseNetInfo()4660 void NetInfoProvided__UseNetInfo()
4661 {
4662 CLBOSStatus lbos_status(true, true);
4663 string service = "/lbos";
4664 CCounterResetter resetter(s_CallCounter);
4665 CConnNetInfo net_info;
4666 CCObjHolder<char> lbos_address(g_LBOS_GetLBOSAddress());
4667 string lbos_addr(lbos_address.Get());
4668 ConnNetInfo_SetUserHeader(*net_info, "My header fq34facsadf");
4669
4670 s_CallCounter = 2; // to get desired behavior from s_FakeResolveIPPort
4671 CMockFunction<FLBOS_ResolveIPPortMethod*> mock(
4672 g_LBOS_UnitTesting_GetLBOSFuncs()->ResolveIPPort, s_FakeResolveIPPort);
4673
4674 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
4675 SERV_LOCALHOST, 0, 0.0,
4676 *net_info, 0, 0, 0, 0, 0));
4677 if (*iter == NULL) {
4678 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter != NULL,
4679 "LBOS not found when it should be");
4680 return;
4681 }
4682 static_cast<SLBOS_Data*>(iter->data)->lbos_addr = lbos_addr.c_str();
4683 HOST_INFO hinfo;
4684 SERV_GetNextInfoEx(*iter, &hinfo);
4685
4686 /* We do not care about results, we care how many IPs algorithm tried
4687 * to resolve service
4688 */
4689 NCBITEST_CHECK_MESSAGE_MT_SAFE(s_LastHeader == "My header fq34facsadf\r\n",
4690 "s_LBOS_FillCandidates: Incorrect "
4691 "transition of header");
4692 }
4693 } /* namespace GetCandidates */
4694
4695
4696 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
4697 namespace GetNextInfo
4698 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
4699 {
4700
EmptyCands__RunGetCandidates()4701 void EmptyCands__RunGetCandidates()
4702 {
4703 CLBOSStatus lbos_status(true, true);
4704 CCounterResetter resetter(s_CallCounter);
4705 string service = "/lbos";
4706 const SSERV_Info* info = NULL;
4707 string hostport = "1.2.3.4:210";
4708 unsigned int host = 0;
4709 unsigned short port = kDefaultPort;
4710 SOCK_StringToHostPort(hostport.c_str(), &host, &port);
4711 CConnNetInfo net_info;
4712 ConnNetInfo_SetUserHeader(*net_info, "My header fq34facsadf");
4713 CMockFunction<FLBOS_FillCandidatesMethod*> mock(
4714 g_LBOS_UnitTesting_GetLBOSFuncs()->FillCandidates,
4715 s_FakeFillCandidates<10>);
4716
4717 /* If no candidates found yet, get candidates and return first of them. */
4718 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
4719 SERV_LOCALHOST, 0, 0.0,
4720 *net_info, 0, 0, 0, 0, 0));
4721 if (*iter == NULL) {
4722 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter != NULL,
4723 "LBOS not found when it should be");
4724 return;
4725 }
4726 /*ConnNetInfo_Destroy(*net_info);*/
4727 HOST_INFO hinfo;
4728 info = SERV_GetNextInfoEx(*iter, &hinfo);
4729 NCBITEST_CHECK_MESSAGE_MT_SAFE(s_CallCounter == 1,
4730 "SERV_GetNextInfoEx: mapper did not ask "
4731 "LBOS for candidates");
4732 NCBITEST_CHECK_MESSAGE_MT_SAFE(info->port == port && info->host == host,
4733 "SERV_GetNextInfoEx: mapper error with "
4734 "first returned element");
4735 NCBITEST_CHECK_MESSAGE_MT_SAFE(hinfo == NULL,
4736 "SERV_GetNextInfoEx: hinfo is not NULL "
4737 "(always should be NULL)");
4738
4739 /* Cleanup */
4740 s_CallCounter = 0;
4741
4742 /* If reset was just made, get candidates and return first of them.
4743 * We do not care about results, we care how many times algorithm tried
4744 * to resolve service */
4745 SERV_Reset(*iter);
4746 info = SERV_GetNextInfoEx(*iter, &hinfo);
4747 NCBITEST_CHECK_MESSAGE_MT_SAFE(s_CallCounter == 1,
4748 "SERV_GetNextInfoEx: mapper did not ask "
4749 "LBOS for candidates");
4750 NCBITEST_CHECK_MESSAGE_MT_SAFE(info->port == port && info->host == host,
4751 "SERV_GetNextInfoEx: mapper error with "
4752 "first returned element");
4753 NCBITEST_CHECK_MESSAGE_MT_SAFE(hinfo == NULL,
4754 "SERV_GetNextInfoEx: hinfo is not NULL "
4755 "(always should be NULL)");
4756 }
4757
4758
ErrorUpdating__ReturnNull()4759 void ErrorUpdating__ReturnNull()
4760 {
4761 CLBOSStatus lbos_status(true, true);
4762 CCounterResetter resetter(s_CallCounter);
4763 string service = "/lbos";
4764 const SSERV_Info* info = NULL;
4765 CConnNetInfo net_info;
4766 CMockFunction<FLBOS_FillCandidatesMethod*> mock(
4767 g_LBOS_UnitTesting_GetLBOSFuncs()->FillCandidates,
4768 s_FakeFillCandidatesWithError);
4769
4770 /*If no candidates found yet, get candidates, catch error and return NULL*/
4771 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
4772 SERV_LOCALHOST, 0, 0.0,
4773 *net_info, 0, 0, 0, 0, 0, 0));
4774 HOST_INFO hinfo = NULL;
4775 info = SERV_GetNextInfoEx(*iter, &hinfo);
4776 NCBITEST_CHECK_MESSAGE_MT_SAFE(info == 0,
4777 "SERV_GetNextInfoEx: mapper did not "
4778 "react correctly to error in LBOS" );
4779 NCBITEST_CHECK_MESSAGE_MT_SAFE(s_CallCounter == 1,
4780 "SERV_GetNextInfoEx:mapper did not "
4781 "react correctly to error in LBOS");
4782 NCBITEST_CHECK_MESSAGE_MT_SAFE(hinfo == NULL,
4783 "SERV_GetNextInfoEx: hinfo is not NULL "
4784 "(always should be NULL)");
4785
4786 /* Cleanup */
4787 s_CallCounter = 0;
4788
4789 /* Now we first play fair, Open() iter, then Reset() iter, and in the
4790 * end simulate error */
4791 mock = s_FakeFillCandidates<10>;
4792 iter = s_SERVOpenP_Safe(service.c_str(), fSERV_All,
4793 SERV_LOCALHOST, 0, 0.0,
4794 *net_info, 0, 0, 0, 0, 0);
4795 /* If reset was just made, get candidates and return firs of them.
4796 * We do not care about results, we care how many times algorithm tried
4797 * to resolve service */
4798 SERV_Reset(*iter);
4799 mock = s_FakeFillCandidatesWithError;
4800 info = SERV_GetNextInfoEx(*iter, &hinfo);
4801 NCBITEST_CHECK_MESSAGE_MT_SAFE(info == 0,
4802 "SERV_GetNextInfoEx: mapper did not "
4803 "react correctly to error in LBOS "
4804 "(info not NULL)" );
4805 NCBITEST_CHECK_MESSAGE_MT_SAFE(s_CallCounter == 2,
4806 "SERV_GetNextInfoEx:mapper did not "
4807 "react correctly to error in LBOS "
4808 "(fillCandidates was not called once)");
4809 NCBITEST_CHECK_MESSAGE_MT_SAFE(hinfo == NULL,
4810 "SERV_GetNextInfoEx: hinfo is not NULL "
4811 "(always should be NULL)");
4812 }
4813
HaveCands__ReturnNext()4814 void HaveCands__ReturnNext()
4815 {
4816 CLBOSStatus lbos_status(true, true);
4817 CCounterResetter resetter(s_CallCounter);
4818 string service = "/lbos";
4819 const SSERV_Info* info = NULL;
4820 unsigned int host = 0;
4821 unsigned short port = kDefaultPort;
4822 CConnNetInfo net_info;
4823
4824 CMockFunction<FLBOS_FillCandidatesMethod*> mock (
4825 g_LBOS_UnitTesting_GetLBOSFuncs()->FillCandidates,
4826 s_FakeFillCandidates<200>);
4827
4828 /* We will get 200 candidates, iterate 220 times and see how the system
4829 * behaves */
4830 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
4831 SERV_LOCALHOST, 0, 0.0,
4832 *net_info, 0, 0, 0, 0, 0));
4833 /*ConnNetInfo_Destroy(*net_info);*/
4834 HOST_INFO hinfo;
4835 NCBITEST_CHECK_MESSAGE_MT_SAFE(s_CallCounter == 1,
4836 "SERV_GetNextInfoEx: mapper did not "
4837 "ask LBOS for candidates");
4838
4839 int i = 0, found_hosts = 0;
4840 ostringstream hostport;
4841 for (i = 0; i < 220/*200+ returned by s_FakeFillCandidates*/; i++)
4842 {
4843 info = SERV_GetNextInfoEx(*iter, &hinfo);
4844 if (info != NULL) { /*As we suppose it will be last 20 iterations */
4845 found_hosts++;
4846 hostport.str("");
4847 hostport << i+1 << "." << i+2 << "." << i+3 << "." << i+4 <<
4848 ":" << (i+1)*210;
4849 SOCK_StringToHostPort(hostport.str().c_str(), &host, &port);
4850 NCBITEST_CHECK_MESSAGE_MT_SAFE(s_CallCounter == 1,
4851 "SERV_GetNextInfoEx: fill "
4852 "candidates was called, but "
4853 "it should not be");
4854 NCBITEST_CHECK_MESSAGE_MT_SAFE(info->port == port &&
4855 info->host == host,
4856 "SERV_GetNextInfoEx: mapper "
4857 "error with 'next' returned "
4858 "element");
4859 NCBITEST_CHECK_MESSAGE_MT_SAFE(hinfo == NULL,
4860 "SERV_GetNextInfoEx: hinfo is not "
4861 "NULL (always should be NULL)");
4862 }
4863 }
4864
4865 /* The main interesting here is to check if info is null, and that
4866 * 'fillcandidates()' was not called again internally*/
4867 NCBITEST_CHECK_MESSAGE_MT_SAFE(info == NULL,
4868 "SERV_GetNextInfoEx: mapper error with "
4869 "'after last' returned element");
4870 stringstream ss;
4871 ss << "Mapper should find 200 hosts, but found " << i;
4872 NCBITEST_CHECK_MESSAGE_MT_SAFE(found_hosts == 200, ss.str().c_str());
4873 }
4874
LastCandReturned__ReturnNull()4875 void LastCandReturned__ReturnNull()
4876 {
4877 CLBOSStatus lbos_status(true, true);
4878 CCounterResetter resetter(s_CallCounter);
4879 string service = "/lbos";
4880 const SSERV_Info* info = NULL;
4881 HOST_INFO hinfo = NULL;
4882 string hostport = "127.0.0.1:80";
4883 unsigned int host = 0;
4884 unsigned short port = 0;
4885 SOCK_StringToHostPort(hostport.c_str(), &host, &port);
4886 CConnNetInfo net_info;
4887
4888 CMockFunction<FLBOS_FillCandidatesMethod*> mock(
4889 g_LBOS_UnitTesting_GetLBOSFuncs()->FillCandidates,
4890 s_FakeFillCandidates<200>);
4891 /* If no candidates found yet, get candidates and return first of them. */
4892 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
4893 SERV_LOCALHOST, 0, 0.0,
4894 *net_info, 0, 0, 0, 0, 0));
4895
4896 /*ConnNetInfo_Destroy(*net_info);*/
4897 NCBITEST_CHECK_MESSAGE_MT_SAFE(s_CallCounter == 1,
4898 "SERV_GetNextInfoEx: mapper did not ask "
4899 "LBOS for candidates");
4900
4901 info = SERV_GetNextInfoEx(*iter, &hinfo);
4902 int i = 0;
4903 for (i = 0; info != NULL; i++) {
4904 info = SERV_GetNextInfoEx(*iter, &hinfo);
4905 }
4906
4907 stringstream ss;
4908 ss << "Mapper should find 200 hosts, but found " << i;
4909 NCBITEST_CHECK_MESSAGE_MT_SAFE(i == 200, ss.str().c_str());
4910 NCBITEST_CHECK_MESSAGE_MT_SAFE(hinfo == NULL,
4911 "SERV_GetNextInfoEx: hinfo is not NULL "
4912 "(always should be NULL)");
4913 }
4914
DataIsNull__ReconstructData()4915 void DataIsNull__ReconstructData()
4916 {
4917 string service = "/lbos";
4918 const SSERV_Info* info = NULL;
4919 string hostport = "1.2.3.4:210";
4920 unsigned int host = 0;
4921 unsigned short port = kDefaultPort;
4922 CCounterResetter resetter(s_CallCounter);
4923 CLBOSStatus lbos_status(true, true);
4924 HOST_INFO hinfo;
4925 SOCK_StringToHostPort(hostport.c_str(), &host, &port);
4926 CConnNetInfo net_info;
4927 CMockFunction<FLBOS_FillCandidatesMethod*> mock(
4928 g_LBOS_UnitTesting_GetLBOSFuncs()->FillCandidates,
4929 s_FakeFillCandidates<10>);
4930
4931
4932 /* We will get iterator, and then delete data from it and run GetNextInfo.
4933 * The mapper should recover from this kind of error */
4934 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
4935 SERV_LOCALHOST, 0, 0.0,
4936 *net_info, 0, 0, 0, 0, 0));
4937 if (*iter == NULL) {
4938 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter != NULL,
4939 "LBOS not found when it should be");
4940 return;
4941 }
4942 /* Now we destroy data */
4943 SLBOS_Data* data = static_cast<SLBOS_Data*>(iter->data);
4944 g_LBOS_UnitTesting_GetLBOSFuncs()->DestroyData(data);
4945 iter->data = NULL;
4946 /* Now let's see how the mapper behaves. Let's check the first element */
4947 info = SERV_GetNextInfoEx(*iter, &hinfo);
4948 /*Assert*/
4949 NCBITEST_CHECK_MESSAGE_MT_SAFE(s_CallCounter == 2,
4950 "SERV_GetNextInfoEx: mapper did "
4951 "not ask LBOS for candidates");
4952 NCBITEST_CHECK_MESSAGE_MT_SAFE(info->port == port && info->host == host,
4953 "SERV_GetNextInfoEx: mapper error "
4954 "with first returned element");
4955 NCBITEST_CHECK_MESSAGE_MT_SAFE(hinfo == NULL,
4956 "SERV_GetNextInfoEx: hinfo is not "
4957 "NULL (always should be NULL)");
4958 }
4959
4960
WrongMapper__ReturnNull()4961 void WrongMapper__ReturnNull()
4962 {
4963 CLBOSStatus lbos_status(true, true);
4964 string service = "/lbos";
4965 const SSERV_Info* info = NULL;
4966 CConnNetInfo net_info;
4967 /* We will get iterator, and then change mapper name from it and run
4968 * GetNextInfo.
4969 * The mapper should return null */
4970 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
4971 SERV_LOCALHOST, 0, 0.0,
4972 *net_info, 0, 0, 0, 0, 0));
4973 if (*iter == NULL) {
4974 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter != NULL,
4975 "LBOS not found when it should be");
4976 return;
4977 }
4978 /*ConnNetInfo_Destroy(*net_info);*/
4979 HOST_INFO hinfo;
4980 const SSERV_VTable* origTable = iter->op;
4981 const SSERV_VTable fakeTable = {NULL, NULL, NULL, NULL, NULL, "LBSMD"};
4982 iter->op = &fakeTable;
4983 /* Now let's see how the mapper behaves. Let's run GetNextInfo()*/
4984 info = SERV_GetNextInfoEx(*iter, &hinfo);
4985
4986 NCBITEST_CHECK_MESSAGE_MT_SAFE(info == NULL,
4987 "SERV_GetNextInfoEx: mapper did not "
4988 "react correctly to wrong mapper name");
4989
4990 iter->op = origTable; /* Because we need to clean iter */
4991 }
4992 } /* namespace GetNextInfo */
4993
4994
4995 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
4996 namespace Open
4997 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
4998 {
4999
NetInfoNull__ConstructNetInfo()5000 void NetInfoNull__ConstructNetInfo()
5001 {
5002 CLBOSStatus lbos_status(true, true);
5003 string service = "/lbos";
5004
5005 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
5006 SERV_LOCALHOST, 0, 0.0,
5007 0, 0, 0, 0, 0, 0));
5008 if (*iter == NULL) {
5009 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter != NULL,
5010 "LBOS not found when it should be");
5011 return;
5012 }
5013 if (iter->op == NULL) {
5014 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op != NULL,
5015 "Mapper returned NULL when it should return s_op");
5016 return;
5017 }
5018 NCBITEST_CHECK_MESSAGE_MT_SAFE(strcmp(iter->op->mapper, "lbos") == 0,
5019 "Name of mapper that returned "
5020 "answer is not \"lbos\"");
5021 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op->Close != NULL, "Close "
5022 "operation pointer is null");
5023 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op->Feedback != NULL,
5024 "Feedback operation pointer is null");
5025 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op->GetNextInfo != NULL,
5026 "GetNextInfo operation pointer is null");
5027 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op->Reset != NULL,
5028 "Reset operation pointer is null");
5029 }
5030
5031
ServerExists__ReturnLbosOperations()5032 void ServerExists__ReturnLbosOperations()
5033 {
5034 CLBOSStatus lbos_status(true, true);
5035 string service = "/lbos";
5036 auto_ptr<SSERV_IterTag> iter(new SSERV_IterTag);
5037 if (iter.get() == NULL) {
5038 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter.get() == NULL,
5039 "Problem with memory allocation, "
5040 "calloc failed. Not enough RAM?");
5041 return;
5042 }
5043 iter->name = service.c_str();
5044 iter->ismask = 0;
5045 iter->arg = NULL;
5046 iter->val = NULL;
5047 CConnNetInfo net_info;
5048
5049 iter->op = SERV_LBOS_Open(iter.get(), *net_info, NULL);
5050 if (iter->op == NULL) {
5051 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op != NULL,
5052 "LBOS not found when it should be");
5053 return;
5054 }
5055
5056 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op != NULL,
5057 "Mapper returned NULL when it should "
5058 "return s_op");
5059 NCBITEST_CHECK_MESSAGE_MT_SAFE(strcmp(iter->op->mapper, "lbos") == 0,
5060 "Name of mapper that returned "
5061 "answer is not \"LBOS\"");
5062 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op->Close != NULL,
5063 "Close operation pointer is null");
5064 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op->Feedback != NULL,
5065 "Feedback operation pointer is null");
5066 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op->GetNextInfo != NULL,
5067 "GetNextInfo operation pointer is null");
5068 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op->Reset != NULL,
5069 "Reset operation pointer is null");
5070
5071 /* Cleanup */
5072 g_LBOS_UnitTesting_GetLBOSFuncs()->
5073 DestroyData(static_cast<SLBOS_Data*>(iter->data));
5074 }
5075
5076
InfoPointerProvided__WriteNull()5077 void InfoPointerProvided__WriteNull()
5078 {
5079 CLBOSStatus lbos_status(true, true);
5080 string service = "/lbos";
5081 auto_ptr<SSERV_IterTag> iter(new SSERV_IterTag);
5082 iter->name = service.c_str();
5083 iter->ismask = 0;
5084 iter->arg = NULL;
5085 iter->val = NULL;
5086 SSERV_Info* info;
5087 CConnNetInfo net_info;
5088
5089 iter->op = SERV_LBOS_Open(iter.get(), *net_info, &info);
5090 if (iter->op == NULL) {
5091 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op != NULL,
5092 "LBOS not found when it should be");
5093 return;
5094 }
5095 NCBITEST_CHECK_MESSAGE_MT_SAFE(strcmp(iter->op->mapper, "lbos") == 0,
5096 "Name of mapper that returned answer "
5097 "is not \"LBOS\"");
5098 NCBITEST_CHECK_MESSAGE_MT_SAFE(info == NULL, "LBOS mapper provided "
5099 "something in host info, "
5100 "when it should not");
5101
5102 /* Cleanup */
5103 g_LBOS_UnitTesting_GetLBOSFuncs()->
5104 DestroyData(static_cast<SLBOS_Data*>(iter->data));
5105 }
5106
NoSuchService__ReturnNull()5107 void NoSuchService__ReturnNull()
5108 {
5109 CLBOSStatus lbos_status(true, true);
5110 string service = "/service/donotexist";
5111
5112 auto_ptr<SSERV_IterTag> iter(new SSERV_IterTag);
5113 NCBITEST_REQUIRE_MESSAGE_MT_SAFE(iter.get() != NULL,
5114 "Problem with memory allocation, "
5115 "calloc failed. Not enough RAM?");
5116 iter->name = service.c_str();
5117 iter->ismask = 0;
5118 iter->arg = NULL;
5119 iter->val = NULL;
5120 CConnNetInfo net_info;
5121 iter->op = SERV_LBOS_Open(iter.get(), *net_info, NULL);
5122 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op == NULL,
5123 "Mapper returned s_op when it "
5124 "should return NULL");
5125 }
5126
Dbaf__AppendDBNameToServiceName()5127 void Dbaf__AppendDBNameToServiceName()
5128 {
5129 CLBOSStatus lbos_status(true, true);
5130 CMockFunction<FLBOS_FillCandidatesMethod*> mock(
5131 g_LBOS_UnitTesting_GetLBOSFuncs()->FillCandidates,
5132 s_FakeFillCandidates<1>);
5133 string service = "dbinfo";
5134 auto_ptr<SSERV_IterTag> iter(new SSERV_IterTag);
5135 iter->name = service.c_str();
5136 iter->ismask = 0;
5137 iter->arg = "dbaf";
5138 iter->val = "pubmed";
5139 SSERV_Info* info;
5140 CConnNetInfo net_info;
5141
5142 iter->op = SERV_LBOS_Open(iter.get(), *net_info, &info);
5143 NCBITEST_REQUIRE_MESSAGE_MT_SAFE(iter->op != NULL,
5144 "LBOS not found when it should be");
5145 NCBITEST_CHECK_EQUAL_MT_SAFE(s_LBOS_servicename, string("dbinfo/pubmed"));
5146 /* Cleanup */
5147 g_LBOS_UnitTesting_GetLBOSFuncs()->
5148 DestroyData(static_cast<SLBOS_Data*>(iter->data));
5149 }
5150
NameIsMask__ReturnNull()5151 void NameIsMask__ReturnNull()
5152 {
5153 CLBOSStatus lbos_status(true, true);
5154 string service = "/lbos";
5155
5156 auto_ptr<SSERV_IterTag> iter(new SSERV_IterTag);
5157 NCBITEST_REQUIRE_MESSAGE_MT_SAFE(iter.get() != NULL,
5158 "Problem with memory allocation, "
5159 "calloc failed. Not enough RAM?");
5160 iter->name = service.c_str();
5161 iter->ismask = 1;
5162 iter->arg = NULL;
5163 iter->val = NULL;
5164 CConnNetInfo net_info;
5165 iter->op = SERV_LBOS_Open(iter.get(), *net_info, NULL);
5166 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op == NULL,
5167 "Mapper returned s_op when it "
5168 "should return NULL");
5169 }
5170
5171 } /* namespace Open */
5172
5173
5174 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
5175 namespace GeneralLBOS
5176 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
5177 {
ServerExists__ServOpenPReturnsLbosOperations()5178 void ServerExists__ServOpenPReturnsLbosOperations()
5179 {
5180 CLBOSStatus lbos_status(true, true);
5181 string service = "/lbos";
5182 CConnNetInfo net_info;
5183 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
5184 SERV_LOCALHOST, 0, 0.0,
5185 *net_info, 0, 0, 0, 0, 0));
5186 if (*iter == NULL) {
5187 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter != NULL,
5188 "LBOS not found when it should be");
5189 return;
5190 }
5191 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op != NULL,
5192 "Mapper returned NULL when it "
5193 "should return s_op");
5194 if (iter->op == NULL) return;
5195 NCBITEST_CHECK_MESSAGE_MT_SAFE(strcmp(iter->op->mapper, "lbos") == 0,
5196 "Name of mapper that returned "
5197 "answer is not \"LBOS\"");
5198 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op->Close != NULL,
5199 "Close operation pointer "
5200 "is null");
5201 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op->Feedback != NULL,
5202 "Feedback operation "
5203 "pointer is null");
5204 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op->GetNextInfo != NULL,
5205 "GetNextInfo operation pointer is null");
5206 NCBITEST_CHECK_MESSAGE_MT_SAFE(iter->op->Reset != NULL,
5207 "Reset operation pointer "
5208 "is null");
5209 }
5210
5211
LbosExist__ShouldWork()5212 void LbosExist__ShouldWork()
5213 {
5214 CLBOSStatus lbos_status(true, true);
5215 s_TestFindMethod(eLBOS_FindMethod_Registry);
5216 s_TestFindMethod(eLBOS_FindMethod_CustomHost);
5217 }
5218
5219
ServerDoesNotExist__ShouldReturnNull()5220 void ServerDoesNotExist__ShouldReturnNull()
5221 {
5222 CLBOSStatus lbos_status(true, true);
5223 string service = "/asdf/idonotexist";
5224 CConnNetInfo net_info;
5225 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
5226 SERV_LOCALHOST, 0, 0.0,
5227 *net_info, 0, 0, 0, 0, 0));
5228 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter == NULL,
5229 "Mapper should not find service, but "
5230 "it somehow found.");
5231 }
5232
5233
DbafUnknownDB__ReturnNull()5234 void DbafUnknownDB__ReturnNull()
5235 {
5236 CLBOSStatus lbos_status(true, true);
5237 string service = "dbinfo";
5238 CConnNetInfo net_info;
5239 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
5240 SERV_LOCALHOST, 0, 0.0,
5241 *net_info, 0, 0, 0,
5242 "dbaf"/*arg*/, "mypubmed"/*val*/));
5243 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter == NULL,
5244 "Mapper should not find service, but "
5245 "it somehow found.");
5246 }
5247
5248
DbafKnownDB__ShouldWork()5249 void DbafKnownDB__ShouldWork()
5250 {
5251 CLBOSStatus lbos_status(true, true);
5252 string service = "dbinfo";
5253 CConnNetInfo net_info;
5254 const SSERV_Info* info = NULL;
5255 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
5256 SERV_LOCALHOST, 0, 0.0,
5257 *net_info, 0, 0, 0,
5258 "dbaf"/*arg*/, "pubmed"/*val*/));
5259 NCBITEST_REQUIRE_MESSAGE_MT_SAFE(*iter != NULL,
5260 "LBOS did not find dbinfo/pubmed");
5261 int servers = -1;
5262 do {
5263 servers++;
5264 info = SERV_GetNextInfoEx(*iter, NULL);
5265 } while (info != NULL);
5266 NCBITEST_CHECK_MESSAGE_MT_SAFE(servers > 0,
5267 "Mapper should find services dbinfo/pubmed, "
5268 "but nothing was found.");
5269 }
5270
NameIsMask__ReturnNull()5271 void NameIsMask__ReturnNull()
5272 {
5273 CLBOSStatus lbos_status(true, true);
5274 string service = "/lbos*";
5275 CConnNetInfo net_info;
5276 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
5277 SERV_LOCALHOST, 0, 0.0,
5278 *net_info, 0, 0, 0, 0, 0));
5279 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter == NULL,
5280 "Mapper should not find service, but "
5281 "it somehow found.");
5282 }
5283
5284 } /* namespace GeneralLBOS */
5285
5286
5287 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
5288 namespace Announcement
5289 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
5290 {
5291
5292
5293 /* 1. Successfully announced : return SUCCESS */
5294 /* Test is thread-safe. */
AllOK__ReturnSuccess()5295 void AllOK__ReturnSuccess()
5296 {
5297 #undef PORT_N
5298 #define PORT_N 1
5299 CLBOSStatus lbos_status(true, true);
5300 CCObjHolder<char> lbos_answer(NULL);
5301 CCObjHolder<char> lbos_status_message(NULL);
5302 string node_name = s_GenerateNodeName();
5303 unsigned short port = kDefaultPort;
5304 unsigned short deannounce_result;
5305 WRITE_LOG("Testing simple announce test. Should return 200.");
5306 int count_before;
5307
5308 /* Prepare for test. We need to be sure that there is no previously
5309 * registered non-deleted service. We count servers with chosen port
5310 * and check if there is no server already announced */
5311 SELECT_PORT(count_before, node_name, port);
5312 unsigned short result;
5313 /*
5314 * I. Check with 0.0.0.0
5315 */
5316 WRITE_LOG("Part I : 0.0.0.0");
5317 result = s_AnnounceCSafe(node_name.c_str(),
5318 "1.0.0",
5319 "",
5320 port,
5321 "http://" ANNOUNCEMENT_HOST_0000 ":" +
5322 s_PortStr(PORT_N) + "/health", "",
5323 &lbos_answer.Get(), &lbos_status_message.Get());
5324
5325 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_Success);
5326
5327 /* Cleanup */
5328 deannounce_result = s_DeannounceC(node_name.c_str(), "1.0.0", NULL,
5329 port, NULL, NULL);
5330 NCBITEST_CHECK_EQUAL_MT_SAFE(deannounce_result, eLBOS_Success);
5331 lbos_answer = NULL;
5332 lbos_status_message = NULL;
5333
5334 /*
5335 * II. Now check with IP
5336 */
5337 WRITE_LOG("Part II: real IP");
5338 node_name = s_GenerateNodeName();
5339 SELECT_PORT(count_before, node_name, port);
5340 s_AnnounceCSafe(node_name.c_str(),
5341 "1.0.0",
5342 "", port,
5343 (string("http://") + ANNOUNCEMENT_HOST + ":" +
5344 s_PortStr(PORT_N) + "/health").c_str(), "",
5345 &lbos_answer.Get(), &lbos_status_message.Get());
5346 /* Count how many servers there are */
5347 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_Success);
5348
5349 /* Cleanup */
5350 s_DeannounceC(node_name.c_str(), "1.0.0", ANNOUNCEMENT_HOST.c_str(),
5351 port, NULL, NULL);
5352 NCBITEST_CHECK_EQUAL_MT_SAFE(deannounce_result, eLBOS_Success);
5353 lbos_answer = NULL;
5354 lbos_status_message = NULL;
5355 #undef PORT_N
5356 #define PORT s_PortStr()
5357 }
5358
5359
5360 /* 3. Successfully announced : char* lbos_answer contains answer of LBOS */
5361 /* Test is thread-safe. */
AllOK__LBOSAnswerProvided()5362 void AllOK__LBOSAnswerProvided()
5363 {
5364 #undef PORT_N
5365 #define PORT_N 2
5366 WRITE_LOG("Testing simple announce test. "
5367 "Announcement function should return answer of LBOS");
5368 WRITE_LOG("Part I : 0.0.0.0");
5369 CLBOSStatus lbos_status(true, true);
5370 CCObjHolder<char> lbos_answer(NULL);
5371 CCObjHolder<char> lbos_status_message(NULL);
5372 /* Prepare for test. We need to be sure that there is no previously
5373 * registered non-deleted service */
5374 string node_name = s_GenerateNodeName();
5375 unsigned short port = kDefaultPort;
5376 /* Prepare for test. We need to be sure that there is no previously
5377 * registered non-deleted service. We count server with chosen port
5378 * and check if there is no server already announced */
5379 int count_before;
5380 SELECT_PORT(count_before, node_name, port);
5381 /* Announce */
5382 s_AnnounceCSafe(node_name.c_str(), "1.0.0", "", port,
5383 (string("http://") + s_GetMyHost() + ":" +
5384 s_PortStr(PORT_N) + "/health").c_str(), "",
5385 &lbos_answer.Get(), &lbos_status_message.Get());
5386
5387 NCBITEST_CHECK_MESSAGE_MT_SAFE(!g_LBOS_StringIsNullOrEmpty(*lbos_answer),
5388 "Announcement function did not return "
5389 "LBOS answer as expected");
5390 /* Cleanup */
5391 s_DeannounceC(node_name.c_str(), "1.0.0", NULL, port, NULL, NULL);
5392 lbos_answer = NULL;
5393 lbos_status_message = NULL;
5394
5395 /* Now check with IP */
5396 WRITE_LOG("Part II: real IP");
5397 SELECT_PORT(count_before, node_name, port);
5398 s_AnnounceCSafe(node_name.c_str(), "1.0.0", "", port,
5399 (string("http://") + ANNOUNCEMENT_HOST + ":" +
5400 s_PortStr(PORT_N) + "/health").c_str(), "",
5401 &lbos_answer.Get(), &lbos_status_message.Get());
5402 NCBITEST_CHECK_MESSAGE_MT_SAFE(!g_LBOS_StringIsNullOrEmpty(*lbos_answer),
5403 "Announcement function did not return "
5404 "LBOS answer as expected");
5405 /* Cleanup */
5406 s_DeannounceC(node_name.c_str(), "1.0.0", ANNOUNCEMENT_HOST.c_str(),
5407 port, NULL, NULL);
5408
5409 lbos_answer = NULL;
5410 lbos_status_message = NULL;
5411 }
5412
5413 /* If announced successfully - status message is "OK" */
AllOK__LBOSStatusMessageIsOK()5414 void AllOK__LBOSStatusMessageIsOK()
5415 {
5416 WRITE_LOG("Testing simple announce test. Announcement function should "
5417 "return answer of LBOS");
5418 WRITE_LOG("Part I : 0.0.0.0");
5419 CLBOSStatus lbos_status(true, true);
5420 CCObjHolder<char> lbos_answer(NULL);
5421 CCObjHolder<char> lbos_status_message(NULL);
5422 /* Prepare for test. We need to be sure that there is no previously
5423 * registered non-deleted service */
5424 string node_name = s_GenerateNodeName();
5425 unsigned short port = kDefaultPort;
5426 /* Prepare for test. We need to be sure that there is no previously
5427 * registered non-deleted service. We count server with chosen port
5428 * and check if there is no server already announced */
5429 int count_before;
5430 SELECT_PORT(count_before, node_name, port);
5431 /* Announce */
5432 s_AnnounceCSafe(node_name.c_str(), "1.0.0", "", port,
5433 (string("http://" ANNOUNCEMENT_HOST_0000 ":") +
5434 s_PortStr(PORT_N) + "/health").c_str(), "",
5435 &lbos_answer.Get(), &lbos_status_message.Get());
5436 /* Count how many servers there are */
5437 NCBITEST_CHECK_EQUAL_MT_SAFE(
5438 string(*lbos_status_message ? *lbos_status_message : "<NULL>"),
5439 string("OK"));
5440 /* Cleanup */
5441 s_DeannounceC(node_name.c_str(), "1.0.0", NULL, port, NULL, NULL);
5442 lbos_answer = NULL;
5443 lbos_status_message = NULL;
5444
5445 /* Now check with IP */
5446 WRITE_LOG("Part II: real IP");
5447 node_name = s_GenerateNodeName();
5448 SELECT_PORT(count_before, node_name, port);
5449 /* Prepare for test. We need to be sure that there is no previously
5450 * registered non-deleted service. We count server with chosen port
5451 * and check if there is no server already announced */
5452 SELECT_PORT(count_before, node_name, port);
5453 s_AnnounceCSafe(node_name.c_str(), "1.0.0", "", port,
5454 (string("http://") + ANNOUNCEMENT_HOST + ":" +
5455 s_PortStr(PORT_N) + "/health").c_str(), "",
5456 &lbos_answer.Get(), &lbos_status_message.Get());
5457 NCBITEST_CHECK_EQUAL_MT_SAFE(
5458 string(*lbos_status_message ? *lbos_status_message : "<NULL>"), "OK");
5459 /* Cleanup */
5460 s_DeannounceC(node_name.c_str(), "1.0.0", ANNOUNCEMENT_HOST.c_str(),
5461 port, NULL, NULL);
5462 lbos_answer = NULL;
5463 lbos_status_message = NULL;
5464 }
5465
5466
5467 /* 4. Successfully announced: information about announcement is saved to
5468 * hidden LBOS mapper's storage */
5469 /* Test is thread-safe. */
AllOK__AnnouncedServerSaved()5470 void AllOK__AnnouncedServerSaved()
5471 {
5472 #undef PORT_N
5473 #define PORT_N 3
5474 WRITE_LOG("Testing saving of parameters of announced server when "
5475 "announcement finished successfully");
5476 WRITE_LOG("Part I : 0.0.0.0");
5477 CLBOSStatus lbos_status(true, true);
5478 CCObjHolder<char> lbos_answer(NULL);
5479 CCObjHolder<char> lbos_status_message(NULL);
5480 /* Prepare for test. We need to be sure that there is no previously
5481 * registered non-deleted service */
5482 string node_name = s_GenerateNodeName();
5483 unsigned short port = kDefaultPort;
5484 /* Prepare for test. We need to be sure that there is no previously
5485 * registered non-deleted service. We count server with chosen port
5486 * and check if there is no server already announced */
5487 int count_before;
5488 SELECT_PORT(count_before, node_name, port);
5489 /* Announce */
5490 unsigned short result;
5491 result = s_AnnounceCSafe(node_name.c_str(), "1.0.0", "", port,
5492 "http://" ANNOUNCEMENT_HOST_0000 ":" +
5493 s_PortStr(PORT_N) + "/health", "",
5494 &lbos_answer.Get(), &lbos_status_message.Get());
5495 NCBITEST_CHECK_MESSAGE_MT_SAFE(result == eLBOS_Success,
5496 "Announcement function did not return "
5497 "SUCCESS as expected");
5498 int find_result = s_FindAnnouncedServer(node_name, "1.0.0", port,
5499 "0.0.0.0");
5500 NCBITEST_CHECK_EQUAL_MT_SAFE(find_result, 1);
5501 /* Cleanup */
5502 lbos_answer = NULL;
5503 lbos_status_message = NULL;
5504 int deannounce_result = s_DeannounceC(node_name.c_str(),
5505 "1.0.0", "", port,
5506 &lbos_answer.Get(),
5507 &lbos_status_message.Get());
5508 NCBITEST_CHECK_MESSAGE_MT_SAFE(deannounce_result == eLBOS_Success,
5509 "Deannouncement function did not return "
5510 "SUCCESS as expected");
5511 /* Cleanup */
5512 lbos_answer = NULL;
5513 lbos_status_message = NULL;
5514
5515 /* Now check with IP instead of host name */
5516 WRITE_LOG("Part II: real IP");
5517 node_name = s_GenerateNodeName();
5518 SELECT_PORT(count_before, node_name, port);
5519 /* Announce */
5520 s_AnnounceCSafe(node_name.c_str(),
5521 "1.0.0",
5522 "",
5523 port,
5524 (string("http://") + ANNOUNCEMENT_HOST +
5525 ":" + s_PortStr(PORT_N) + "/health").c_str(),
5526 "",
5527 &lbos_answer.Get(), &lbos_status_message.Get());
5528 NCBITEST_CHECK_MESSAGE_MT_SAFE(result == eLBOS_Success,
5529 "Announcement function did not return "
5530 "SUCCESS as expected");
5531 find_result = s_FindAnnouncedServer(node_name, "1.0.0", port,
5532 ANNOUNCEMENT_HOST);
5533 NCBITEST_CHECK_EQUAL_MT_SAFE(find_result, 1);
5534 /* Cleanup */
5535 lbos_answer = NULL;
5536 lbos_status_message = NULL;
5537 deannounce_result = s_DeannounceC(node_name.c_str(), "1.0.0", "",
5538 port, NULL, NULL);
5539 NCBITEST_CHECK_EQUAL_MT_SAFE(deannounce_result, eLBOS_Success);
5540 lbos_answer = NULL;
5541 lbos_status_message = NULL;
5542 #undef PORT_N
5543 #define PORT_N 0
5544 }
5545
5546
5547 /* 5. Could not find LBOS: return NO_LBOS */
5548 /* Test is NOT thread-safe. */
NoLBOS__ReturnNoLBOSAndNotFind()5549 void NoLBOS__ReturnNoLBOSAndNotFind()
5550 {
5551 WRITE_LOG("Testing behavior of LBOS when no LBOS is found."
5552 " Should return eLBOS_LbosNotFound");
5553 CLBOSStatus lbos_status(true, true);
5554 unsigned short result;
5555 string node_name = s_GenerateNodeName();
5556 unsigned short port = kDefaultPort;
5557 CCObjHolder<char> lbos_answer(NULL);
5558 CCObjHolder<char> lbos_status_message(NULL);
5559 WRITE_LOG("Mocking CONN_Read() with s_FakeReadEmpty()");
5560
5561 /* Announce */
5562 CMockFunction<FLBOS_ConnReadMethod*> mock(
5563 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
5564 s_FakeReadEmpty);
5565
5566 result = s_AnnounceC(node_name,
5567 "1.0.0", "", port,
5568 "http://" ANNOUNCEMENT_HOST_0000 ":" +
5569 s_PortStr(PORT_N) + "/health", "",
5570 &lbos_answer.Get(), &lbos_status_message.Get());
5571 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_LbosNotFound);
5572
5573 /* Cleanup*/
5574 WRITE_LOG("Reverting mock of CONN_Read() with s_FakeReadEmpty()");
5575 }
5576
5577
5578 /* 6. Could not find LBOS : char* lbos_answer is set to NULL */
5579 /* Test is NOT thread-safe. */
NoLBOS__LBOSAnswerNull()5580 void NoLBOS__LBOSAnswerNull()
5581 {
5582 WRITE_LOG(
5583 "Testing behavior of LBOS when no LBOS is found."
5584 " LBOS answer should be NULL.");
5585 CLBOSStatus lbos_status(true, true);
5586 string node_name = s_GenerateNodeName();
5587 unsigned short port = kDefaultPort;
5588 CCObjHolder<char> lbos_answer(NULL);
5589 CCObjHolder<char> lbos_status_message(NULL);
5590 WRITE_LOG(
5591 "Mocking CONN_Read() with s_FakeReadEmpty()");
5592
5593 /* Announce */
5594 CMockFunction<FLBOS_ConnReadMethod*> mock(
5595 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
5596 s_FakeReadEmpty);
5597 s_AnnounceC(node_name.c_str(),
5598 "1.0.0",
5599 "", port,
5600 "http://" ANNOUNCEMENT_HOST_0000 ":" +
5601 s_PortStr(PORT_N) + "/health", "",
5602 &lbos_answer.Get(), &lbos_status_message.Get());
5603 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
5604 "LBOS status message is not NULL");
5605
5606 /* Cleanup*/
5607 WRITE_LOG("Reverting mock of CONN_Read() with s_FakeReadEmpty()");
5608 }
5609
5610
5611 /* 6. Could not find LBOS: char* lbos_status_message is set to NULL */
5612 /* Test is NOT thread-safe. */
NoLBOS__LBOSStatusMessageNull()5613 void NoLBOS__LBOSStatusMessageNull()
5614 {
5615 CLBOSStatus lbos_status(true, true);
5616 string node_name = s_GenerateNodeName();
5617 unsigned short port = kDefaultPort;
5618 CCObjHolder<char> lbos_answer(NULL);
5619 CCObjHolder<char> lbos_status_message(NULL);
5620 WRITE_LOG("Testing behavior of LBOS when no LBOS is found. "
5621 "LBOS message should be NULL.");
5622 WRITE_LOG("Mocking CONN_Read() with s_FakeReadEmpty()");
5623
5624 /* Announce */
5625 CMockFunction<FLBOS_ConnReadMethod*> mock(
5626 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
5627 s_FakeReadEmpty);
5628 s_AnnounceC(node_name.c_str(),
5629 "1.0.0",
5630 "", port,
5631 "http://" ANNOUNCEMENT_HOST_0000 ":" +
5632 s_PortStr(PORT_N) + "/health", "",
5633 &lbos_answer.Get(), &lbos_status_message.Get());
5634 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
5635 "Answer from LBOS was not NULL");
5636
5637 /* Cleanup*/
5638 WRITE_LOG("Reverting mock of CONN_Read() with s_FakeReadEmpty()");
5639 }
5640
5641
5642 /* 8. LBOS returned error: return eLBOS_Server */
5643 /* Test is NOT thread-safe. */
LBOSError__ReturnServerErrorCode()5644 void LBOSError__ReturnServerErrorCode()
5645 {
5646 CLBOSStatus lbos_status(true, true);
5647 CCObjHolder<char> lbos_answer(NULL);
5648 CCObjHolder<char> lbos_status_message(NULL);
5649 string node_name = s_GenerateNodeName();
5650 unsigned short port = kDefaultPort;
5651 WRITE_LOG("Testing behavior of LBOS "
5652 "mapper when LBOS returns error code (507).");
5653 WRITE_LOG("Mocking CONN_Read() with "
5654 "s_FakeReadAnnouncementWithErrorFromLBOS()");
5655
5656 /* Announce */
5657 CMockFunction<FLBOS_ConnReadMethod*> mock(
5658 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
5659 s_FakeReadAnnouncementWithErrorFromLBOS);
5660 unsigned short result;
5661 result = s_AnnounceC(node_name.c_str(), "1.0.0", "", port,
5662 "http://" ANNOUNCEMENT_HOST_0000 ":" +
5663 s_PortStr(PORT_N) + "/health", "",
5664 &lbos_answer.Get(), &lbos_status_message.Get());
5665
5666 /* Check that error code is the same as in mock*/
5667 NCBITEST_CHECK_MESSAGE_MT_SAFE(result == 507,
5668 "Announcement did not return "
5669 "eLBOS_DNSResolve as expected");
5670 /* Cleanup*/
5671 WRITE_LOG("Reverting mock of CONN_Read() with s_FakeReadEmpty()");
5672 }
5673
5674
5675 /* 8.5. LBOS returned error: return eLBOS_Server */
5676 /* Test is NOT thread-safe. */
LBOSError__ReturnServerStatusMessage()5677 void LBOSError__ReturnServerStatusMessage()
5678 {
5679 CLBOSStatus lbos_status(true, true);
5680 CCObjHolder<char> lbos_answer(NULL);
5681 CCObjHolder<char> lbos_status_message(NULL);
5682 string node_name = s_GenerateNodeName();
5683 unsigned short port = kDefaultPort;
5684 WRITE_LOG("Testing behavior of LBOS "
5685 "mapper when LBOS returns error message "
5686 "(\"LBOS STATUS\").");
5687 WRITE_LOG("Mocking CONN_Read() with "
5688 "s_FakeReadAnnouncementWithErrorFromLBOS()");
5689 CMockFunction<FLBOS_ConnReadMethod*> mock(
5690 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
5691 s_FakeReadAnnouncementWithErrorFromLBOS);
5692 s_AnnounceC(node_name.c_str(), "1.0.0", "", port,
5693 "http://" ANNOUNCEMENT_HOST_0000 ":" +
5694 s_PortStr(PORT_N) + "/health", "",
5695 &lbos_answer.Get(), &lbos_status_message.Get());
5696
5697 /* Check that error code is the same as in mock*/
5698 NCBITEST_CHECK_MESSAGE_MT_SAFE(strcmp(*lbos_status_message, "LBOS STATUS")
5699 == 0,
5700 "Announcement did not return "
5701 "eLBOS_DNSResolve as expected");
5702 /* Cleanup*/
5703 WRITE_LOG("Reverting mock of CONN_Read() with "
5704 "s_FakeReadAnnouncementWithErrorFromLBOS()");
5705 }
5706
5707
5708 /* 9. LBOS returned error : char* lbos_answer contains answer of LBOS */
5709 /* Test is NOT thread-safe. */
LBOSError__LBOSAnswerProvided()5710 void LBOSError__LBOSAnswerProvided()
5711 {
5712 CLBOSStatus lbos_status(true, true);
5713 CCObjHolder<char> lbos_answer(NULL);
5714 CCObjHolder<char> lbos_status_message(NULL);
5715 string node_name = s_GenerateNodeName();
5716 unsigned short port = kDefaultPort;
5717 WRITE_LOG("Testing behavior of LBOS "
5718 "mapper when LBOS returns error code. Should return "
5719 "exact message from LBOS");
5720 WRITE_LOG("Mocking CONN_Read() with "
5721 "s_FakeReadAnnouncementWithErrorFromLBOS()");
5722 CMockFunction<FLBOS_ConnReadMethod*> mock(
5723 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
5724 s_FakeReadAnnouncementWithErrorFromLBOS);
5725 s_AnnounceC(node_name.c_str(), "1.0.0", "", port,
5726 "http://" ANNOUNCEMENT_HOST_0000 ":" +
5727 s_PortStr(PORT_N) + "/health", "",
5728 &lbos_answer.Get(), &lbos_status_message.Get());
5729 NCBITEST_CHECK_EQUAL_MT_SAFE(string(*lbos_answer ? *lbos_answer : "<NULL>"),
5730 "Those lbos errors are scaaary");
5731 /* Cleanup*/
5732 WRITE_LOG("Reverting mock of CONN_Read() with "
5733 "s_FakeReadAnnouncementWithErrorFromLBOS()");
5734 }
5735
5736
5737 /* 11. Server announced again(service name, IP and port coincide) and
5738 * announcement in the same zone, replace old info about announced
5739 * server in internal storage with new one. */
5740 /* Test is thread-safe. */
AlreadyAnnouncedInTheSameZone__ReplaceInStorage()5741 void AlreadyAnnouncedInTheSameZone__ReplaceInStorage()
5742 {
5743 #undef PORT_N
5744 #define PORT_N 0
5745 WRITE_LOG("Testing behavior of LBOS "
5746 "mapper when server was already announced (info stored in "
5747 "internal storage should be replaced. Server node should be "
5748 "rewritten, no duplicates.");
5749 unsigned int lbos_addr = 0;
5750 unsigned short lbos_port = 0;
5751 CLBOSStatus lbos_status(true, true);
5752 CCObjHolder<char> lbos_answer(NULL);
5753 CCObjHolder<char> lbos_status_message(NULL);
5754 string node_name = s_GenerateNodeName();
5755 unsigned short port = kDefaultPort;
5756
5757 /* Prepare for test. We need to be sure that there is no previously
5758 * registered non-deleted service. We count server with chosen port
5759 * and check if there is no server already announced */
5760 int count_before;
5761 SELECT_PORT(count_before, node_name, port);
5762 unsigned short result;
5763 const char* convert_result;
5764 /*
5765 * First time
5766 */
5767 WRITE_LOG("Part 1. First time announcing server");
5768 result = s_AnnounceCSafe(node_name.c_str(), "1.0.0", "", port,
5769 "http://" ANNOUNCEMENT_HOST_0000 ":" +
5770 s_PortStr(PORT_N) + "/health", "",
5771 &lbos_answer.Get(), &lbos_status_message.Get());
5772 NCBITEST_REQUIRE_MESSAGE_MT_SAFE(!g_LBOS_StringIsNullOrEmpty(*lbos_answer),
5773 "Did not get answer after announcement");
5774 convert_result =
5775 SOCK_StringToHostPort(*lbos_answer, &lbos_addr, &lbos_port);
5776 NCBITEST_CHECK_MESSAGE_MT_SAFE(convert_result != NULL,
5777 "Host:port returned by LBOS is trash");
5778 /* Count how many servers there are */
5779 int count_after = 0;
5780 count_after = s_CountServersWithExpectation(node_name, port, 1,
5781 __LINE__, kDiscoveryDelaySec);
5782 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after, count_before + 1);
5783 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_Success);
5784 WRITE_LOG("Trying to find the announced server in "
5785 "%LBOS%/lbos/text/service");
5786 int servers_in_text_service = s_FindAnnouncedServer(node_name, "1.0.0",
5787 port, "0.0.0.0");
5788 WRITE_LOG("Found " << servers_in_text_service <<
5789 " servers in %LBOS%/lbos/text/service (should be " <<
5790 count_before + 1 << ")");
5791
5792 NCBITEST_CHECK_EQUAL_MT_SAFE(servers_in_text_service, count_before + 1);
5793 lbos_answer = NULL;
5794 lbos_status_message = NULL;
5795 /*
5796 * Second time
5797 */
5798 WRITE_LOG("Part 2. Second time announcing server");
5799 result = s_AnnounceCSafe(node_name.c_str(), "1.0.0", "", port,
5800 "http://" ANNOUNCEMENT_HOST_0000 ":" +
5801 s_PortStr(PORT_N) + "/health", "",
5802 &lbos_answer.Get(), &lbos_status_message.Get());
5803 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_Success);
5804 NCBITEST_REQUIRE_MESSAGE_MT_SAFE(!g_LBOS_StringIsNullOrEmpty(*lbos_answer),
5805 "Did not get answer after announcement");
5806 convert_result = SOCK_StringToHostPort(*lbos_answer,
5807 &lbos_addr,
5808 &lbos_port);
5809 NCBITEST_CHECK_MESSAGE_MT_SAFE(convert_result != NULL &&
5810 convert_result != *lbos_answer,
5811 "LBOS answer could not be parsed to host:port");
5812 /* Count how many servers there are. */
5813 count_after = s_CountServersWithExpectation(node_name, port, 1, __LINE__,
5814 kDiscoveryDelaySec);
5815 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after, count_before + 1);
5816 WRITE_LOG("Trying to find the announced server in "
5817 "%LBOS%/lbos/text/service");
5818 servers_in_text_service = s_FindAnnouncedServer(node_name, "1.0.0",
5819 port, "0.0.0.0");
5820 WRITE_LOG("Found " << servers_in_text_service <<
5821 " servers in %LBOS%/lbos/text/service (should be " <<
5822 count_before + 1 << ")");
5823
5824 NCBITEST_CHECK_EQUAL_MT_SAFE(servers_in_text_service, count_before + 1);
5825
5826 /* Cleanup */
5827 int deannounce_result = s_DeannounceC(node_name.c_str(),
5828 "1.0.0", ANNOUNCEMENT_HOST.c_str(),
5829 port, NULL, NULL);
5830 NCBITEST_CHECK_EQUAL_MT_SAFE(deannounce_result, eLBOS_Success);
5831 #undef PORT_N
5832 #define PORT_N 0
5833 }
5834
5835
5836 /* 12. Trying to announce in foreign domain - do nothing and
5837 return that no LBOS is found (because no LBOS in current
5838 domain is found) */
5839 /* Test is NOT thread-safe. */
ForeignDomain__NoAnnounce()5840 void ForeignDomain__NoAnnounce()
5841 {
5842 #if 0 /* deprecated */
5843 /* Test is not run in TeamCity*/
5844 if (!getenv("TEAMCITY_VERSION")) {
5845 CLBOSStatus lbos_status(true, true);
5846 CCObjHolder<char> lbos_answer(NULL);
5847 CCObjHolder<char> lbos_status_message(NULL);
5848 unsigned short port = kDefaultPort;
5849 string node_name = s_GenerateNodeName();
5850 WRITE_LOG("Testing behavior of LBOS mapper when no LBOS is "
5851 "available in the current region (should "
5852 "return error code eLBOS_LbosNotFound).");
5853 WRITE_LOG("Mocking region with \"or-wa\"");
5854 CMockString mock1(*g_LBOS_UnitTesting_CurrentDomain(), "or-wa");
5855
5856 unsigned short result;
5857 result = s_AnnounceC(node_name.c_str(), "1.0.0", "", port,
5858 "http://" ANNOUNCEMENT_HOST_0000 ":" + s_PortStr(PORT_N) + "/health",
5859 &lbos_answer.Get(), &lbos_status_message.Get());
5860 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_LbosNotFound);
5861 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
5862 "LBOS status message is not NULL");
5863 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
5864 "Answer from LBOS was not NULL");
5865 /* Cleanup*/
5866 WRITE_LOG("Reverting mock of region with \"or-wa\"");
5867 }
5868 #endif
5869 }
5870
5871
5872 /* 13. Was passed incorrect healthcheck URL(NULL or empty not starting with
5873 * "http(s)://") : do not announce and return INVALID_ARGS */
5874 /* Test is thread-safe. */
IncorrectURL__ReturnInvalidArgs()5875 void IncorrectURL__ReturnInvalidArgs()
5876 {
5877 #undef PORT_N
5878 #define PORT_N 4
5879 CLBOSStatus lbos_status(true, true);
5880 CCObjHolder<char> lbos_answer(NULL);
5881 CCObjHolder<char> lbos_status_message(NULL);
5882 string node_name = s_GenerateNodeName();
5883 unsigned short port = kDefaultPort;
5884 WRITE_LOG("Testing behavior of LBOS "
5885 "mapper when passed incorrect healthcheck URL - should return "
5886 "eLBOS_InvalidArgs");
5887 /* Count how many servers there are before we announce */
5888 /*
5889 * I. Healthcheck URL that equals NULL
5890 */
5891 WRITE_LOG("Part I. Healthcheck is <NULL>");
5892 unsigned short result;
5893 result = s_AnnounceC(node_name.c_str(), "1.0.0", "", port, NULL, NULL,
5894 &lbos_answer.Get(), &lbos_status_message.Get());
5895 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_InvalidArgs);
5896 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
5897 "LBOS status message is not NULL");
5898 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
5899 "Answer from LBOS was not NULL");
5900 /* Cleanup*/
5901 lbos_answer = NULL;
5902 lbos_status_message = NULL;
5903
5904 /*
5905 * II. Healthcheck URL that does not start with http or https
5906 */
5907 WRITE_LOG("Part II. Healthcheck is \"\" (empty string)");
5908 port = kDefaultPort;
5909 node_name = s_GenerateNodeName();
5910 s_AnnounceC(node_name.c_str(), "1.0.0", "", port, "", NULL,
5911 &lbos_answer.Get(), &lbos_status_message.Get());
5912 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_InvalidArgs);
5913 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
5914 "LBOS status message is not NULL");
5915 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
5916 "Answer from LBOS was not NULL");
5917
5918 /*
5919 * III. Healthcheck URL that does not start with http or https
5920 */
5921 WRITE_LOG("Part III. Healthcheck is \""
5922 "lbos.dev.be-md.ncbi.nlm.nih.gov:8080/health\" (no http://)");
5923 port = kDefaultPort;
5924 node_name = s_GenerateNodeName();
5925 s_AnnounceC(node_name.c_str(), "1.0.0", "", port,
5926 "lbos.dev.be-md.ncbi.nlm.nih.gov:8080/health", NULL,
5927 &lbos_answer.Get(), &lbos_status_message.Get());
5928 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_InvalidArgs);
5929 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
5930 "LBOS status message is not NULL");
5931 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
5932 "Answer from LBOS was not NULL");
5933 #undef PORT_N
5934 #define PORT_N 0
5935 }
5936
5937
5938 /* 14. Was passed incorrect port: do not announce and return
5939 * INVALID_ARGS */
5940 /* Test is thread-safe. */
IncorrectPort__ReturnInvalidArgs()5941 void IncorrectPort__ReturnInvalidArgs()
5942 {
5943 #undef PORT_N
5944 #define PORT_N 5
5945 CLBOSStatus lbos_status(true, true);
5946 CCObjHolder<char> lbos_answer(NULL);
5947 string node_name = s_GenerateNodeName();
5948 CCObjHolder<char> lbos_status_message(NULL);
5949 unsigned short port = kDefaultPort;
5950 WRITE_LOG("Testing behavior of LBOS "
5951 "mapper when passed incorrect port (zero) - should return "
5952 "eLBOS_InvalidArgs");
5953 unsigned short result;
5954 /* I. 0 */
5955 port = 0;
5956 result = s_AnnounceC(node_name.c_str(), "1.0.0", "", port,
5957 ("http://" ANNOUNCEMENT_HOST_0000 ":" +
5958 s_PortStr(PORT_N) + "/health").c_str(), NULL,
5959 &lbos_answer.Get(), &lbos_status_message.Get());
5960 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_InvalidArgs);
5961 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
5962 "LBOS status message is not NULL");
5963 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
5964 "Answer from LBOS was not NULL");
5965 #undef PORT_N
5966 #define PORT_N 0
5967 }
5968
5969
5970 /* 15. Was passed incorrect version(NULL or empty) : do not announce and
5971 * return INVALID_ARGS */
5972 /* Test is thread-safe. */
IncorrectVersion__ReturnInvalidArgs()5973 void IncorrectVersion__ReturnInvalidArgs()
5974 {
5975 #undef PORT_N
5976 #define PORT_N 6
5977 CLBOSStatus lbos_status(true, true);
5978 CCObjHolder<char> lbos_answer(NULL);
5979 string node_name = s_GenerateNodeName();
5980 CCObjHolder<char> lbos_status_message(NULL);
5981 unsigned short port = kDefaultPort;
5982 unsigned short result;
5983 WRITE_LOG("Testing behavior of LBOS "
5984 "mapper when passed incorrect version - should return "
5985 "eLBOS_InvalidArgs");
5986 /*
5987 * I. NULL version
5988 */
5989 WRITE_LOG("Part I. Version is <NULL>");
5990 result = s_AnnounceC(node_name.c_str(), NULL, "", port,
5991 ("http://" ANNOUNCEMENT_HOST_0000 ":" +
5992 s_PortStr(PORT_N) + "/health").c_str(), NULL,
5993 &lbos_answer.Get(), &lbos_status_message.Get());
5994 /* Count how many servers there are */
5995 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_InvalidArgs);
5996 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
5997 "LBOS status message is not NULL");
5998 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
5999 "Answer from LBOS was not NULL");
6000
6001 /* Cleanup */
6002 lbos_answer = NULL;
6003 lbos_status_message = NULL;
6004
6005 /*
6006 * II. Empty version
6007 */
6008 WRITE_LOG("Part II. Version is \"\" (empty string)");
6009 node_name = s_GenerateNodeName();
6010 result = s_AnnounceC(node_name.c_str(), "", "", port,
6011 ("http://" ANNOUNCEMENT_HOST_0000 ":" +
6012 s_PortStr(PORT_N) + "/health").c_str(), NULL,
6013 &lbos_answer.Get(), &lbos_status_message.Get());
6014 /* Count how many servers there are */
6015 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_InvalidArgs);
6016 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
6017 "LBOS status message is not NULL");
6018 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
6019 "Answer from LBOS was not NULL");
6020 #undef PORT_N
6021 #define PORT_N 0
6022 }
6023
6024
6025 /* 16. Was passed incorrect service name (NULL or empty): do not
6026 * announce and return INVALID_ARGS */
6027 /* Test is thread-safe. */
IncorrectServiceName__ReturnInvalidArgs()6028 void IncorrectServiceName__ReturnInvalidArgs()
6029 {
6030 #undef PORT_N
6031 #define PORT_N 7
6032 unsigned short result;
6033 CLBOSStatus lbos_status(true, true);
6034 CCObjHolder<char> lbos_answer(NULL);
6035 string node_name = s_GenerateNodeName();
6036 CCObjHolder<char> lbos_status_message(NULL);
6037 unsigned short port = kDefaultPort;
6038 WRITE_LOG("Testing behavior of LBOS "
6039 "mapper when passed incorrect service name - should return "
6040 "eLBOS_InvalidArgs");
6041 /*
6042 * I. NULL service name
6043 */
6044 WRITE_LOG("Part I. Service name is <NULL>");
6045 result = s_AnnounceC(NULL, "1.0.0", "", port,
6046 ("http://" ANNOUNCEMENT_HOST_0000 ":" +
6047 s_PortStr(PORT_N) + "/health").c_str(), NULL,
6048 &lbos_answer.Get(), &lbos_status_message.Get());
6049 /* Count how many servers there are */
6050 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_InvalidArgs);
6051 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
6052 "LBOS status message is not NULL");
6053 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
6054 "Answer from LBOS was not NULL");
6055 /* Cleanup */
6056 lbos_answer = NULL;
6057 lbos_status_message = NULL;
6058
6059 /*
6060 * II. Empty service name
6061 */
6062 WRITE_LOG("Part II. Service name is \"\" (empty string)");
6063 node_name = s_GenerateNodeName();
6064 port = kDefaultPort;
6065 /* As the call is not supposed to go through mapper to network,
6066 * we do not need any mocks*/
6067 result = s_AnnounceC("", "1.0.0", "", port,
6068 ("http://" ANNOUNCEMENT_HOST_0000 ":" +
6069 s_PortStr(PORT_N) + "/health").c_str(), NULL,
6070 &lbos_answer.Get(), &lbos_status_message.Get());
6071 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_InvalidArgs);
6072 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
6073 "LBOS status message is not NULL");
6074 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
6075 "Answer from LBOS was not NULL");
6076 #undef PORT_N
6077 #define PORT_N 0
6078 }
6079
6080
6081 /* 17. Real-life test : after announcement server should be visible to
6082 * resolve */
6083 /* Test is thread-safe. */
RealLife__VisibleAfterAnnounce()6084 void RealLife__VisibleAfterAnnounce()
6085 {
6086 #undef PORT_N
6087 #define PORT_N 7
6088 CLBOSStatus lbos_status(true, true);
6089 CCObjHolder<char> lbos_answer(NULL);
6090 CCObjHolder<char> lbos_status_message(NULL);
6091 unsigned short port = kDefaultPort;
6092 string node_name = s_GenerateNodeName();
6093 WRITE_LOG("Real-life test of LBOS: "
6094 "after announcement, number of servers with specific name, "
6095 "port and version should increase by 1");
6096 /* Prepare for test. We need to be sure that there is no previously
6097 * registered non-deleted service. We count server with chosen port
6098 * and check if there is no server already announced */
6099 int count_before;
6100 SELECT_PORT(count_before, node_name, port);
6101 unsigned short result;
6102 result = s_AnnounceCSafe(node_name, "1.0.0", "", port,
6103 ("http://" ANNOUNCEMENT_HOST_0000 ":" +
6104 s_PortStr(PORT_N) + "/health").c_str(), "",
6105 &lbos_answer.Get(), &lbos_status_message.Get());
6106 int count_after = s_CountServersWithExpectation(node_name, port, 1,
6107 __LINE__,
6108 kDiscoveryDelaySec);
6109 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_Success);
6110 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after, count_before + 1);
6111 /* Cleanup */
6112 s_DeannounceC(node_name.c_str(), "1.0.0", "", port, NULL, NULL);
6113 #undef PORT_N
6114 #define PORT_N 0
6115 }
6116
6117
6118 /* 18. If was passed "0.0.0.0" as IP, change 0.0.0.0 to real IP */
6119 /* Test is NOT thread-safe. */
IP0000__ReplaceWithIP()6120 void IP0000__ReplaceWithIP()
6121 {
6122 CLBOSStatus lbos_status(true, true);
6123 /* Here we mock SOCK_gethostbyaddrEx to specify IP address that we want to
6124 * expect in place of "0.0.0.0" */
6125 CCObjHolder<char> lbos_answer(NULL);
6126 string node_name = s_GenerateNodeName();
6127 CCObjHolder<char> lbos_status_message(NULL);
6128 unsigned short port = kDefaultPort;
6129 WRITE_LOG("If healthcheck has 0.0.0.0 specified as host: "
6130 "it should be sent as-is to LBOS");
6131 /* Prepare for test. We need to be sure that there is no previously
6132 * registered non-deleted service. We count server with chosen port
6133 * and check if there is no server already announced */
6134 int count_before;
6135 SELECT_PORT(count_before, node_name, port);
6136 WRITE_LOG("Mocking SOCK_gethostbyaddr with \"1.2.3.4\"");
6137 CMockFunction<FLBOS_SOCKGetLocalHostAddressMethod*> mock1(
6138 g_LBOS_UnitTesting_GetLBOSFuncs()->LocalHostAddr,
6139 s_FakeGetLocalHostAddress<true, 1, 2, 3, 4>);
6140 WRITE_LOG("Mocking Announce with fake Anonounce");
6141 CMockFunction<FLBOS_AnnounceMethod*> mock2 (
6142 g_LBOS_UnitTesting_GetLBOSFuncs()->AnnounceEx,
6143 s_FakeAnnounceEx);
6144 unsigned short result;
6145 string health = "http://" ANNOUNCEMENT_HOST_0000 ":" + s_PortStr(PORT_N) +
6146 "/health";
6147 result = s_AnnounceC(node_name, "1.0.0", "", port,
6148 health.c_str(), "",
6149 &lbos_answer.Get(), &lbos_status_message.Get());
6150 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_DNSResolve);
6151 stringstream healthcheck;
6152 healthcheck << "http%3A%2F%2F1.2.3.4%3A" + s_PortStr(PORT_N) + "%2Fhealth"
6153 << "%2Fport" << port << "%2Fhost%2Fversion1.0.0";
6154 NCBITEST_CHECK_EQUAL_MT_SAFE(s_LBOS_hostport, healthcheck.str().c_str());
6155 lbos_answer = NULL;
6156 lbos_status_message = NULL;
6157
6158 WRITE_LOG("Mocking SOCK_gethostbyaddr with \"251.252.253.147\"");
6159 mock1 = s_FakeGetLocalHostAddress<true, 251, 252, 253, 147>;
6160 s_AnnounceC(node_name, "1.0.0", "", port,
6161 ("http://" ANNOUNCEMENT_HOST_0000 ":" +
6162 s_PortStr(PORT_N) + "/health").c_str(), "",
6163 &lbos_answer.Get(), &lbos_status_message.Get());
6164 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_DNSResolve);
6165 healthcheck.str(std::string());
6166 healthcheck << "http%3A%2F%2F251.252.253.147%3A" + s_PortStr(PORT_N) +
6167 "%2Fhealth" << "%2Fport" << port <<
6168 "%2Fhost%2Fversion1.0.0";
6169 NCBITEST_CHECK_EQUAL_MT_SAFE(s_LBOS_hostport, healthcheck.str().c_str());
6170 /* Cleanup*/
6171 WRITE_LOG("Reverting mock of SOCK_gethostbyaddr");
6172 WRITE_LOG("Reverting mock of Announce with fake Anonounce");
6173 }
6174
6175
6176 /* 19. Was passed "0.0.0.0" as IP and could not manage to resolve local host
6177 * IP - return eLBOS_DNSResolve */
6178 /* Test is NOT thread-safe. */
ResolveLocalIPError__ReturnDNSError()6179 void ResolveLocalIPError__ReturnDNSError()
6180 {
6181 CLBOSStatus lbos_status(true, true);
6182 CCObjHolder<char> lbos_answer(NULL);
6183 CCObjHolder<char> lbos_status_message(NULL);
6184 string node_name = s_GenerateNodeName();
6185 WRITE_LOG("If healthcheck has 0.0.0.0 specified as host, "
6186 "and running SOCK_gethostbyaddr returns error: "
6187 "do not care, because we do not substitute 0.0.0.0, "
6188 "we send it as it is");
6189 unsigned short port = kDefaultPort;
6190 WRITE_LOG("Mocking SOCK_gethostbyaddr with \"0.0.0.0\"");
6191 CMockFunction<FLBOS_SOCKGetLocalHostAddressMethod*> mock(
6192 g_LBOS_UnitTesting_GetLBOSFuncs()->LocalHostAddr,
6193 s_FakeGetLocalHostAddress<false,0,0,0,0>);
6194 unsigned short result;
6195 result = s_AnnounceC(node_name, "1.0.0", "", port,
6196 ("http://" ANNOUNCEMENT_HOST_0000 ":" +
6197 s_PortStr(PORT_N) + "/health").c_str(), "",
6198 &lbos_answer.Get(), &lbos_status_message.Get());
6199 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_DNSResolve);
6200 /* Cleanup*/
6201 lbos_answer = NULL;
6202 result = s_DeannounceC(node_name.c_str(), "1.0.0", "", port,
6203 &lbos_answer.Get(), NULL);
6204 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_DNSResolve);
6205 WRITE_LOG("Reverting mock og SOCK_gethostbyaddr with \"0.0.0.0\"");
6206 }
6207
6208
6209 /* 20. LBOS is OFF - return eLBOS_Disabled */
6210 /* Test is NOT thread-safe. */
LBOSOff__ReturnKLBOSOff()6211 void LBOSOff__ReturnKLBOSOff()
6212 {
6213 CCObjHolder<char> lbos_answer(NULL);
6214 CLBOSStatus lbos_status(true, false);
6215 CCObjHolder<char> lbos_status_message(NULL);
6216 unsigned short port = 8080;
6217 unsigned short result;
6218 WRITE_LOG("LBOS mapper is OFF (maybe it is not turned ON in registry "
6219 "or it could not initialize at start) - return eLBOS_Disabled");
6220 result = s_AnnounceC("lbostest", "1.0.0", "", port,
6221 "http://" ANNOUNCEMENT_HOST_0000 ":" +
6222 s_PortStr(PORT_N) + "/health", "",
6223 &lbos_answer.Get(), &lbos_status_message.Get());
6224 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_Disabled);
6225 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
6226 "LBOS status message is not NULL");
6227 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
6228 "Answer from LBOS was not NULL");
6229 }
6230
6231
6232 /*21. Announced successfully, but LBOS return corrupted answer -
6233 return 454 */
6234 /* Test is NOT thread-safe. */
LBOSAnnounceCorruptOutput__Return454()6235 void LBOSAnnounceCorruptOutput__Return454()
6236 {
6237 CLBOSStatus lbos_status(true, true);
6238 CCObjHolder<char> lbos_answer(NULL);
6239 string node_name = s_GenerateNodeName();
6240 CCObjHolder<char> lbos_status_message(NULL);
6241 unsigned short port = kDefaultPort;
6242 WRITE_LOG("Announced successfully, but LBOS returns corrupted answer - "
6243 "return eLBOS_Protocol");
6244 WRITE_LOG("Mocking CONN_Read with corrupt output");
6245 CMockFunction<FLBOS_ConnReadMethod*> mock(
6246 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
6247 s_FakeReadAnnouncementSuccessWithCorruptOutputFromLBOS);
6248 unsigned short result;
6249 result = s_AnnounceC(node_name, "1.0.0", "", port,
6250 "http://" ANNOUNCEMENT_HOST_0000 ":" +
6251 s_PortStr(PORT_N) + "/health", "",
6252 &lbos_answer.Get(), &lbos_status_message.Get());
6253 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_Protocol);
6254 /* Cleanup */
6255 WRITE_LOG("Reverting mock of CONN_Read with corrupt output");
6256 }
6257
6258
6259 /*22. Trying to announce server and providing dead healthcheck URL -
6260 return code from LBOS (200). If healthcheck is at non-existent domain -
6261 return 400 */
6262 /* Test is thread-safe. */
HealthcheckDead__ReturnKLBOSSuccess()6263 void HealthcheckDead__ReturnKLBOSSuccess()
6264 {
6265 CLBOSStatus lbos_status(true, true);
6266 CCObjHolder<char> lbos_answer(NULL);
6267 string node_name = s_GenerateNodeName();
6268 CCObjHolder<char> lbos_status_message(NULL);
6269 unsigned short port = kDefaultPort;
6270 unsigned short result;
6271 WRITE_LOG("Trying to announce server providing dead healthcheck URL - "
6272 "return code from LBOS(200). If healthcheck is at non - existent "
6273 "domain - return 400");
6274 /*
6275 * I. Healthcheck is dead completely
6276 */
6277 WRITE_LOG("Part I. Healthcheck is \"http://badhealth.gov\" - "
6278 "return eLBOS_BadRequest");
6279 result = s_AnnounceC(node_name.c_str(), "1.0.0", "", port,
6280 "http://badhealth.gov", NULL,
6281 &lbos_answer.Get(), &lbos_status_message.Get());
6282 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_BadRequest);
6283 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
6284 "Answer from LBOS was not NULL");
6285 NCBITEST_CHECK_EQUAL_MT_SAFE(
6286 string(*lbos_status_message ? *lbos_status_message : "<NULL>"),
6287 "Bad Request");
6288 /* Cleanup */
6289 lbos_answer = NULL;
6290 s_DeannounceC(node_name.c_str(), "1.0.0", "", port, &lbos_answer.Get(),
6291 NULL);
6292 lbos_answer = NULL;
6293 lbos_status_message = NULL;
6294 /*
6295 * II. Healthcheck returns 404
6296 */
6297 WRITE_LOG("Part II. Healthcheck is \"http:/0.0.0.0:4097/healt\" - "
6298 "return eLBOS_Success");
6299 result = s_AnnounceC(node_name.c_str(), "1.0.0", "", port,
6300 "http://0.0.0.0:4097/healt"/*wrong port*/, NULL,
6301 &lbos_answer.Get(), &lbos_status_message.Get());
6302 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_Success);
6303 NCBITEST_CHECK_MESSAGE_MT_SAFE(!g_LBOS_StringIsNullOrEmpty(*lbos_answer),
6304 "Answer from LBOS was NULL");
6305 NCBITEST_CHECK_EQUAL_MT_SAFE(
6306 string(*lbos_status_message ? *lbos_status_message : "<NULL>"), "OK");
6307 /* Cleanup */
6308 lbos_answer = NULL;
6309 lbos_status_message = NULL;
6310 s_DeannounceC(node_name.c_str(), "1.0.0", "", port, &lbos_answer.Get(),
6311 NULL);
6312 }
6313
6314
6315 /*23. Trying to announce server and providing dead healthcheck URL -
6316 server should be announced */
6317 /* Test is thread-safe. */
HealthcheckDead__AnnouncementOK()6318 void HealthcheckDead__AnnouncementOK()
6319 {
6320 CLBOSStatus lbos_status(true, true);
6321 CCObjHolder<char> lbos_answer(NULL);
6322 string node_name = s_GenerateNodeName();
6323 CCObjHolder<char> lbos_status_message(NULL);
6324 unsigned short port = kDefaultPort;
6325 WRITE_LOG("Trying to announce server providing dead healthcheck URL - "
6326 "server should be announced");
6327
6328 s_AnnounceC(node_name.c_str(), "1.0.0", "", port,
6329 "http://0.0.0.0:4097/healt"/*wrong port*/, NULL,
6330 &lbos_answer.Get(), &lbos_status_message.Get());
6331 stringstream healthcheck;
6332 healthcheck << ":4097/healt" << "?port=" << port <<
6333 "&host=" << "" << "&version=1.0.0";
6334 bool was_announced = s_CheckIfAnnounced(node_name, "1.0.0", port,
6335 healthcheck.str().c_str());
6336 NCBITEST_CHECK_EQUAL_MT_SAFE(was_announced, true);
6337 lbos_answer = NULL;
6338 s_DeannounceC(node_name.c_str(), "1.0.0", "", port, &lbos_answer.Get(), NULL);
6339 }
6340
6341
6342 } /* namespace Announcement */
6343
6344 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
6345 namespace AnnouncementRegistry /* These tests are NOT for multithreading */
6346 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
6347 {
6348 /* 1. All parameters good (Custom section has all parameters correct in
6349 config) - return eLBOS_Success */
ParamsGood__ReturnSuccess()6350 void ParamsGood__ReturnSuccess()
6351 {
6352 CLBOSStatus lbos_status(true, true);
6353 CCObjHolder<char> lbos_answer(NULL);
6354 CCObjHolder<char> lbos_status_message(NULL);
6355 unsigned short result;
6356 WRITE_LOG("Simple announcement from registry. "
6357 "Should return eLBOS_Success");
6358 result = s_AnnounceCRegistry(NULL, &lbos_answer.Get(),
6359 &lbos_status_message.Get());
6360 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_Success);
6361 NCBITEST_CHECK_MESSAGE_MT_SAFE(!g_LBOS_StringIsNullOrEmpty(*lbos_answer),
6362 "Successful announcement did not end up "
6363 "with answer from LBOS");
6364 NCBITEST_CHECK_EQUAL_MT_SAFE(
6365 string(*lbos_status_message ? *lbos_status_message : "<NULL>"), "OK");
6366 /* Cleanup */
6367 s_DeannounceAll();
6368 }
6369
6370 /* 2. Custom section has nothing in config - return eLBOS_InvalidArgs */
CustomSectionNoVars__ReturnInvalidArgs()6371 void CustomSectionNoVars__ReturnInvalidArgs()
6372 {
6373 CLBOSStatus lbos_status(true, true);
6374 CCObjHolder<char> lbos_answer(NULL);
6375 CCObjHolder<char> lbos_status_message(NULL);
6376 unsigned short result;
6377 WRITE_LOG("Custom section has nothing in config - "
6378 "return eLBOS_InvalidArgs");
6379 result = s_AnnounceCRegistry("EMPTY_SECTION",
6380 &lbos_answer.Get(),
6381 &lbos_status_message.Get());
6382 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_InvalidArgs);
6383 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
6384 "LBOS status message is not NULL");
6385 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
6386 "Answer from LBOS was not NULL");
6387 }
6388
6389 /* 3. Section empty or NULL (should use default section and return
6390 eLBOS_Success, if section is Good) */
CustomSectionEmptyOrNullAndDefaultSectionIsOk__ReturnSuccess()6391 void CustomSectionEmptyOrNullAndDefaultSectionIsOk__ReturnSuccess()
6392 {
6393 CLBOSStatus lbos_status(true, true);
6394 CCObjHolder<char> lbos_answer(NULL);
6395 CCObjHolder<char> lbos_status_message(NULL);
6396 unsigned short result;
6397 WRITE_LOG("Section empty or NULL - should use default section and return "
6398 "eLBOS_Success, if section is Good)");
6399 /*
6400 * I. NULL section
6401 */
6402 result = s_AnnounceCRegistry(NULL, &lbos_answer.Get(),
6403 &lbos_status_message.Get());
6404 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_Success);
6405 NCBITEST_CHECK_MESSAGE_MT_SAFE(!g_LBOS_StringIsNullOrEmpty(*lbos_answer),
6406 "Successful announcement did not end up "
6407 "with answer from LBOS");
6408 NCBITEST_CHECK_EQUAL_MT_SAFE(
6409 string(*lbos_status_message ? *lbos_status_message : "<NULL>"), "OK");
6410 /* Cleanup */
6411 s_DeannounceAll();
6412 lbos_answer = NULL;
6413 lbos_status_message = NULL;
6414 /*
6415 * II. Empty section
6416 */
6417 result = s_AnnounceCRegistry("", &lbos_answer.Get(),
6418 &lbos_status_message.Get());
6419 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_Success);
6420 NCBITEST_CHECK_MESSAGE_MT_SAFE(!g_LBOS_StringIsNullOrEmpty(*lbos_answer),
6421 "Successful announcement did not end up with "
6422 "answer from LBOS");
6423 NCBITEST_CHECK_EQUAL_MT_SAFE(
6424 string(*lbos_status_message ? *lbos_status_message : "<NULL>"), "OK");
6425 /* Cleanup */
6426 s_DeannounceAll();
6427 lbos_answer = NULL;
6428 }
6429
6430
TestNullOrEmptyField(const char * field_tested)6431 void TestNullOrEmptyField(const char* field_tested)
6432 {
6433 CLBOSStatus lbos_status (true, true);
6434 CCObjHolder<char> lbos_answer (NULL);
6435 unsigned short result;
6436 CCObjHolder<char> lbos_status_message (NULL);
6437 string null_section = "SECTION_WITHOUT_";
6438 string empty_section = "SECTION_WITH_EMPTY_";
6439 string field_name = field_tested;
6440 /*
6441 * I. NULL section
6442 */
6443 WRITE_LOG("Part I. " << field_tested << " is not in section (NULL)");
6444 result = s_AnnounceCRegistry((null_section + field_name).c_str(),
6445 &lbos_answer.Get(),
6446 &lbos_status_message.Get());
6447 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_InvalidArgs);
6448 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
6449 "LBOS status message is not NULL");
6450 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
6451 "Answer from LBOS was not NULL");
6452 /* Cleanup */
6453 lbos_answer = NULL;
6454 lbos_status_message = NULL;
6455 /*
6456 * II. Empty section
6457 */
6458 WRITE_LOG("Part II. " << field_tested << " is an empty string");
6459 result = s_AnnounceCRegistry((empty_section + field_name).c_str(),
6460 &lbos_answer.Get(),
6461 &lbos_status_message.Get());
6462 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_InvalidArgs);
6463 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
6464 "LBOS status message is not NULL");
6465 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
6466 "Answer from LBOS was not NULL");
6467 }
6468
6469 /* 4. Service is empty or NULL - return eLBOS_InvalidArgs */
ServiceEmptyOrNull__ReturnInvalidArgs()6470 void ServiceEmptyOrNull__ReturnInvalidArgs()
6471 {
6472 WRITE_LOG("Service is empty or NULL - return eLBOS_InvalidArgs");
6473 TestNullOrEmptyField("SERVICE");
6474 }
6475
6476 /* 5. Version is empty or NULL - return eLBOS_InvalidArgs */
VersionEmptyOrNull__ReturnInvalidArgs()6477 void VersionEmptyOrNull__ReturnInvalidArgs()
6478 {
6479 WRITE_LOG("Version is empty or NULL - return eLBOS_InvalidArgs");
6480 TestNullOrEmptyField("VERSION");
6481 }
6482
6483 /* 6. Port is empty or NULL - return eLBOS_InvalidArgs */
PortEmptyOrNull__ReturnInvalidArgs()6484 void PortEmptyOrNull__ReturnInvalidArgs()
6485 {
6486 WRITE_LOG("Port is empty or NULL - return eLBOS_InvalidArgs");
6487 TestNullOrEmptyField("PORT");
6488 }
6489
6490 /* 7. Port is out of range - return eLBOS_InvalidArgs */
PortOutOfRange__ReturnInvalidArgs()6491 void PortOutOfRange__ReturnInvalidArgs()
6492 {
6493 WRITE_LOG("Port is out of range - return eLBOS_InvalidArgs");
6494 CLBOSStatus lbos_status(true, true);
6495 CCObjHolder<char> lbos_answer(NULL);
6496 CCObjHolder<char> lbos_status_message(NULL);
6497 unsigned short result;
6498 /*
6499 * I. port = 0
6500 */
6501 WRITE_LOG("Part I. Port is 0");
6502 result = s_AnnounceCRegistry("SECTION_WITH_PORT_OUT_OF_RANGE1",
6503 &lbos_answer.Get(),
6504 &lbos_status_message.Get());
6505 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_InvalidArgs);
6506 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
6507 "LBOS status message is not NULL");
6508 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
6509 "Answer from LBOS was not NULL");
6510 /* Cleanup */
6511 lbos_answer = NULL;
6512 lbos_status_message = NULL;
6513 /*
6514 * II. port = 100000
6515 */
6516 WRITE_LOG("Part II. Port is 100000");
6517 result = s_AnnounceCRegistry("SECTION_WITH_PORT_OUT_OF_RANGE2",
6518 &lbos_answer.Get(),
6519 &lbos_status_message.Get());
6520 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_InvalidArgs);
6521 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
6522 "LBOS status message is not NULL");
6523 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
6524 "Answer from LBOS was not NULL");
6525 /* Cleanup */
6526 lbos_answer = NULL;
6527 lbos_status_message = NULL;
6528 /*
6529 * III. port = 65536
6530 */
6531 WRITE_LOG("Part III. Port is 65536");
6532 result = s_AnnounceCRegistry("SECTION_WITH_PORT_OUT_OF_RANGE3",
6533 &lbos_answer.Get(),
6534 &lbos_status_message.Get());
6535 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_InvalidArgs);
6536 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
6537 "LBOS status message is not NULL");
6538 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
6539 "Answer from LBOS was not NULL");
6540 }
6541
6542 /* 8. Port contains letters - return eLBOS_InvalidArgs */
PortContainsLetters__ReturnInvalidArgs()6543 void PortContainsLetters__ReturnInvalidArgs()
6544 {
6545 WRITE_LOG("Port contains letters - return eLBOS_InvalidArgs");
6546 CLBOSStatus lbos_status(true, true);
6547 CCObjHolder<char> lbos_answer(NULL);
6548 CCObjHolder<char> lbos_status_message(NULL);
6549 unsigned short result;
6550 result = s_AnnounceCRegistry("SECTION_WITH_CORRUPTED_PORT",
6551 &lbos_answer.Get(),
6552 &lbos_status_message.Get());
6553 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_InvalidArgs);
6554 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
6555 "LBOS status message is not NULL");
6556 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
6557 "Answer from LBOS was not NULL");
6558 /* Cleanup */
6559 lbos_answer = NULL;
6560 }
6561
6562 /* 9. Healthcheck is empty or NULL - return eLBOS_InvalidArgs */
HealthchecktEmptyOrNull__ReturnInvalidArgs()6563 void HealthchecktEmptyOrNull__ReturnInvalidArgs()
6564 {
6565 WRITE_LOG("Healthcheck is empty or NULL - return eLBOS_InvalidArgs");
6566 TestNullOrEmptyField("HEALTHCHECK");
6567 }
6568
6569 /* 10. Healthcheck does not start with http:// or https:// - return
6570 eLBOS_InvalidArgs */
HealthcheckDoesNotStartWithHttp__ReturnInvalidArgs()6571 void HealthcheckDoesNotStartWithHttp__ReturnInvalidArgs()
6572 {
6573 WRITE_LOG("Healthcheck does not start with http:// or https:// - return "
6574 "eLBOS_InvalidArgs");
6575 CLBOSStatus lbos_status(true, true);
6576 CCObjHolder<char> lbos_answer(NULL);
6577 CCObjHolder<char> lbos_status_message(NULL);
6578 unsigned short result;
6579 result = s_AnnounceCRegistry("SECTION_WITH_CORRUPTED_HEALTHCHECK",
6580 &lbos_answer.Get(),
6581 &lbos_status_message.Get());
6582 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_InvalidArgs);
6583 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
6584 "LBOS status message is not NULL");
6585 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
6586 "Answer from LBOS was not NULL");
6587 /* Cleanup */
6588 lbos_answer = NULL;
6589 }
6590 /* 11. Trying to announce server providing dead healthcheck URL -
6591 return eLBOS_Success (previously was eLbosNotFound) */
HealthcheckDead__ReturnKLBOSSuccess()6592 void HealthcheckDead__ReturnKLBOSSuccess()
6593 {
6594 WRITE_LOG("Trying to announce server providing dead healthcheck URL - "
6595 "return eLBOS_Success(previously was eLbosNotFound)");
6596 CLBOSStatus lbos_status (true, true);
6597 CCObjHolder<char> lbos_answer (NULL);
6598 CCObjHolder<char> lbos_status_message (NULL);
6599 unsigned short result;
6600 /* 1. Non-existent domain in healthcheck */
6601 WRITE_LOG("Part I. Healthcheck is \"http://badhealth.gov\" - "
6602 "return eLBOS_BadRequest");
6603 result = s_AnnounceCRegistry("SECTION_WITH_HEALTHCHECK_DNS_ERROR",
6604 &lbos_answer.Get(), &lbos_status_message.Get());
6605 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_BadRequest);
6606 NCBITEST_CHECK_EQUAL_MT_SAFE(
6607 string(*lbos_status_message ? *lbos_status_message : "<NULL>"),
6608 "Bad Request");
6609 NCBITEST_CHECK_EQUAL_MT_SAFE(*lbos_answer, (char*)NULL);
6610 /* Cleanup */
6611 lbos_answer = NULL;
6612 lbos_status_message = NULL;
6613
6614 /* 2. Healthcheck is reachable but does not answer */
6615 WRITE_LOG("Part II. Healthcheck is \"http:/0.0.0.0:4097/healt\" - "
6616 "return eLBOS_Success");
6617 result = s_AnnounceCRegistry("SECTION_WITH_DEAD_HEALTHCHECK",
6618 &lbos_answer.Get(), &lbos_status_message.Get());
6619 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_Success);
6620 NCBITEST_CHECK_EQUAL_MT_SAFE(
6621 string(*lbos_status_message ? *lbos_status_message : "<NULL>"), "OK");
6622 NCBITEST_CHECK_MESSAGE_MT_SAFE(!g_LBOS_StringIsNullOrEmpty(*lbos_answer),
6623 "Answer from LBOS was NULL");
6624 /* Cleanup */
6625 s_DeannounceAll();
6626 lbos_answer = NULL;
6627 lbos_status_message = NULL;
6628 }
6629 }
6630
6631
6632 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
6633 namespace Deannouncement
6634 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
6635 {
6636 /* 1. Successfully de-announced: return eLBOS_Success */
6637 /* Test is thread-safe. */
Deannounced__Return1(unsigned short port)6638 void Deannounced__Return1(unsigned short port)
6639 {
6640 #undef PORT_N
6641 #define PORT_N 8
6642 WRITE_LOG("Successfully de-announced: return eLBOS_Success");
6643 CLBOSStatus lbos_status(true, true);
6644 CCObjHolder<char> lbos_status_message(NULL);
6645 CCObjHolder<char> lbos_answer(NULL);
6646 string node_name = s_GenerateNodeName();
6647 unsigned short result;
6648 /* Prepare for test. We need to be sure that there is no previously
6649 * registered non-deleted service. We count server with chosen port
6650 * and check if there is no server already announced */
6651 int count_before;
6652 SELECT_PORT(count_before, node_name, port);
6653 /*
6654 * I. Check with 0.0.0.0
6655 */
6656 WRITE_LOG("Part I. 0.0.0.0");
6657 s_AnnounceCSafe(node_name.c_str(), "1.0.0", "", port,
6658 ("http://" ANNOUNCEMENT_HOST_0000 ":" +
6659 s_PortStr(PORT_N) + "/health").c_str(), "",
6660 &lbos_answer.Get(), &lbos_status_message.Get());
6661 lbos_answer = NULL;
6662 lbos_status_message = NULL;
6663 /* Count how many servers there are */
6664 int count_after = s_CountServersWithExpectation(node_name, port, 1,
6665 __LINE__,
6666 kDiscoveryDelaySec);
6667 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after, count_before + 1);
6668
6669 result = s_DeannounceC(node_name.c_str(), "1.0.0", "", port,
6670 &lbos_answer.Get(), &lbos_status_message.Get());
6671 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_Success);
6672 NCBITEST_CHECK_EQUAL_MT_SAFE(
6673 string(*lbos_status_message ? *lbos_status_message : "<NULL>"), "OK");
6674 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
6675 "Answer from LBOS was not NULL");
6676 /* Cleanup */
6677 lbos_answer = NULL;
6678 lbos_status_message = NULL;
6679
6680 /*
6681 * II. Now check with IP instead of 0.0.0.0
6682 */
6683 WRITE_LOG("Part II. IP");
6684 node_name = s_GenerateNodeName();
6685 SELECT_PORT(count_before, node_name, port);
6686 s_AnnounceCSafe(node_name.c_str(), "1.0.0", "", port,
6687 (string("http://") + ANNOUNCEMENT_HOST +
6688 ":" + s_PortStr(PORT_N) + "/health").c_str(), "",
6689 &lbos_answer.Get(), &lbos_status_message.Get());
6690 lbos_answer = NULL;
6691 lbos_status_message = NULL;
6692
6693 /* Count how many servers there are */
6694 count_after = s_CountServersWithExpectation(node_name, port, 1, __LINE__,
6695 kDiscoveryDelaySec);
6696 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after, count_before + 1);
6697
6698 result = s_DeannounceC(node_name.c_str(),
6699 "1.0.0", s_GetMyIP().c_str(), port,
6700 &lbos_answer.Get(), &lbos_status_message.Get());
6701 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_Success);
6702 NCBITEST_CHECK_EQUAL_MT_SAFE(
6703 string(*lbos_status_message ? *lbos_status_message : "<NULL>"), "OK");
6704 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
6705 "Answer from LBOS was not NULL");
6706 #undef PORT_N
6707 #define PORT_N 0
6708 }
6709
6710
6711 /* 2. Successfully de-announced : if announcement was saved in local storage,
6712 * remove it */
6713 /* Test is thread-safe. */
Deannounced__AnnouncedServerRemoved()6714 void Deannounced__AnnouncedServerRemoved()
6715 {
6716 #undef PORT_N
6717 #define PORT_N 9
6718 WRITE_LOG("Successfully de-announced : if announcement was saved in local "
6719 "storage, remove it");
6720 CLBOSStatus lbos_status(true, true);
6721 CCObjHolder<char> lbos_answer(NULL);
6722 CCObjHolder<char> lbos_status_message(NULL);
6723 /* Prepare for test. We need to be sure that there is no previously
6724 * registered non-deleted service */
6725 string node_name = s_GenerateNodeName();
6726 unsigned short port = kDefaultPort;
6727 /* Prepare for test. We need to be sure that there is no previously
6728 * registered non-deleted service. We count server with chosen port
6729 * and check if there is no server already announced */
6730 int count_before;
6731 SELECT_PORT(count_before, node_name, port);
6732 unsigned short result;
6733 /*
6734 * I. Check with hostname
6735 */
6736 WRITE_LOG("Part I. Check with hostname");
6737 s_AnnounceCSafe(node_name.c_str(), "1.0.0", "", port,
6738 (string("http://") + s_GetMyHost() + ":8080/health").c_str(),
6739 "", &lbos_answer.Get(), &lbos_status_message.Get());
6740 lbos_answer = NULL;
6741 lbos_status_message = NULL;
6742 int find_result = s_FindAnnouncedServer(node_name, "1.0.0", port, s_GetMyHost());
6743 NCBITEST_CHECK_EQUAL_MT_SAFE(find_result, 1);
6744 result = s_DeannounceC(node_name.c_str(),
6745 "1.0.0",
6746 s_GetMyHost().c_str(),
6747 port, &lbos_answer.Get(),
6748 &lbos_status_message.Get());
6749 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_Success);
6750 NCBITEST_CHECK_EQUAL_MT_SAFE(
6751 string(*lbos_status_message ? *lbos_status_message : "<NULL>"), "OK");
6752 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
6753 "Answer from LBOS was not NULL");
6754 find_result = s_FindAnnouncedServer(node_name, "1.0.0", port, s_GetMyHost());
6755 NCBITEST_CHECK_EQUAL_MT_SAFE(find_result, 0);
6756 lbos_answer = NULL;
6757 lbos_status_message = NULL;
6758
6759 /*
6760 * II. Now check with IP instead of host name
6761 */
6762 WRITE_LOG("Part II. Check with IP");
6763 node_name = s_GenerateNodeName();
6764 SELECT_PORT(count_before, node_name, port);
6765 s_AnnounceCSafe(node_name.c_str(), "1.0.0", "", port,
6766 (string("http://") + ANNOUNCEMENT_HOST +
6767 ":8080/health").c_str(), "",
6768 &lbos_answer.Get(), &lbos_status_message.Get());
6769 /* Count how many servers there are */
6770 find_result = s_FindAnnouncedServer(node_name, "1.0.0", port, s_GetMyIP());
6771 NCBITEST_CHECK_EQUAL_MT_SAFE(find_result, 1);
6772 /* Cleanup */
6773 lbos_answer = NULL;
6774 lbos_status_message = NULL;
6775 /* Deannounce */
6776 result = s_DeannounceC(node_name.c_str(), "1.0.0",
6777 s_GetMyIP().c_str(), port,
6778 &lbos_answer.Get(), &lbos_status_message.Get());
6779 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_Success);
6780 NCBITEST_CHECK_EQUAL_MT_SAFE(
6781 string(*lbos_status_message ? *lbos_status_message : "<NULL>"), "OK");
6782 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
6783 "Answer from LBOS was not NULL");
6784 find_result = s_FindAnnouncedServer(node_name, "1.0.0", port, s_GetMyIP());
6785 NCBITEST_CHECK_EQUAL_MT_SAFE(find_result, 0);
6786 /* Cleanup */
6787 lbos_answer = NULL;
6788 lbos_status_message = NULL;
6789
6790 /*
6791 * III. Now check with "0.0.0.0"
6792 */
6793 WRITE_LOG("Part III. Check with 0.0.0.0");
6794 node_name = s_GenerateNodeName();
6795 SELECT_PORT(count_before, node_name, port);
6796 s_AnnounceCSafe(node_name.c_str(), "1.0.0", "", port,
6797 "http://0.0.0.0:8080/health", "",
6798 &lbos_answer.Get(), &lbos_status_message.Get());
6799 find_result = s_FindAnnouncedServer(node_name, "1.0.0", port, "0.0.0.0");
6800 /* Count how many servers there are */
6801 NCBITEST_CHECK_EQUAL_MT_SAFE(find_result, 1);
6802 /* Cleanup */
6803 lbos_answer = NULL;
6804 lbos_status_message = NULL;
6805 /* Deannounce */
6806 result = s_DeannounceC(node_name.c_str(), "1.0.0",
6807 "", port,
6808 &lbos_answer.Get(), &lbos_status_message.Get());
6809 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_Success);
6810 NCBITEST_CHECK_EQUAL_MT_SAFE(
6811 string(*lbos_status_message ? *lbos_status_message : "<NULL>"), "OK");
6812 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
6813 "Answer from LBOS was not NULL");
6814 find_result = s_FindAnnouncedServer(node_name, "1.0.0", port, "0.0.0.0");
6815 NCBITEST_CHECK_EQUAL_MT_SAFE(find_result, 0);
6816 #undef PORT_N
6817 #define PORT_N 0
6818 }
6819
6820
6821 /* 3. Could not connect to provided LBOS: fail and return 0 */
6822 /* Test is NOT thread-safe. */
NoLBOS__Return0()6823 void NoLBOS__Return0()
6824 {
6825 WRITE_LOG("Could not connect to provided LBOS: fail and return 0");
6826 CLBOSStatus lbos_status(true, true);
6827 CCObjHolder<char> lbos_answer(NULL);
6828 CCObjHolder<char> lbos_status_message(NULL);
6829 unsigned short result;
6830 string node_name = s_GenerateNodeName();
6831 unsigned short port = kDefaultPort;
6832 WRITE_LOG("Mocking CONN_Read with Read_Empty");
6833 CMockFunction<FLBOS_ConnReadMethod*> mock(
6834 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
6835 s_FakeReadEmpty);
6836 result = s_DeannounceC(node_name.c_str(), "1.0.0", "", port,
6837 &lbos_answer.Get(), &lbos_status_message.Get());
6838 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_LbosNotFound);
6839 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
6840 "LBOS status message is not NULL");
6841 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
6842 "Answer from LBOS was not NULL");
6843 WRITE_LOG("Reverting mock of CONN_Read with Read_Empty");
6844 }
6845
6846
6847 /* 4. Successfully connected to LBOS, but deannounce returned 400:
6848 * return 400 */
6849 /* Test is thread-safe. */
LBOSExistsDeannounce400__Return400()6850 void LBOSExistsDeannounce400__Return400()
6851 {
6852 WRITE_LOG("Test: 1) Successfully connected to LBOS,\n "
6853 "2) deannounce returned 400:\n"
6854 "return 400");
6855 CLBOSStatus lbos_status(true, true);
6856 CCObjHolder<char> lbos_answer(NULL);
6857 CCObjHolder<char> lbos_status_message(NULL);
6858 /* Currently LBOS does not return any errors */
6859 /* Here we can try to deannounce something non-existent */
6860 unsigned short result;
6861 unsigned short port = kDefaultPort;
6862 result = s_DeannounceC("no such service", "no such version",
6863 "127.0.0.1", port,
6864 &lbos_answer.Get(), &lbos_status_message.Get());
6865 NCBITEST_CHECK_EQUAL_MT_SAFE(result, 400);
6866 NCBITEST_CHECK_EQUAL_MT_SAFE(
6867 string(*lbos_status_message ? *lbos_status_message : "<NULL>"),
6868 "Bad Request");
6869 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
6870 "Answer from LBOS was not NULL");
6871 }
6872
6873
6874 /* 5. Real - life test : after de-announcement server should be invisible
6875 * to resolve */
6876 /* Test is thread-safe. */
RealLife__InvisibleAfterDeannounce()6877 void RealLife__InvisibleAfterDeannounce()
6878 {
6879 WRITE_LOG("Real-life test : after de-announcement server should "
6880 "be invisible to resolve");
6881 CLBOSStatus lbos_status(true, true);
6882 /* It is best to take test Deannounced__Return1() and just check number
6883 * of servers after the test */
6884 string node_name = s_GenerateNodeName();
6885 unsigned short port = kDefaultPort;
6886 /* Prepare for test. We need to be sure that there is no previously
6887 * registered non-deleted service. We count server with chosen port
6888 * and check if there is no server already announced */
6889 int count_before;
6890 SELECT_PORT(count_before, node_name, port);
6891 Deannounced__Return1(port);
6892 int count_after = s_CountServersWithExpectation(node_name, port, 0,
6893 __LINE__,
6894 kDiscoveryDelaySec);
6895 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after - count_before, 0);
6896 }
6897
6898
6899 /*6. If trying to deannounce in another domain - should return eLBOS_LbosNotFound */
6900 /* We fake our domain so no address looks like our own domain */
6901 /* Test is NOT thread-safe. */
ForeignDomain__DoNothing()6902 void ForeignDomain__DoNothing()
6903 {
6904 #if 0 /* deprecated */
6905 /* Test is not run in TeamCity*/
6906 if (!getenv("TEAMCITY_VERSION")) {
6907 WRITE_LOG("Deannounce in another domain - return eLBOS_LbosNotFound");
6908 CLBOSStatus lbos_status(true, true);
6909 CCObjHolder<char> lbos_answer(NULL);
6910 CCObjHolder<char> lbos_status_message(NULL);
6911 unsigned short result;
6912 string node_name = s_GenerateNodeName();
6913 unsigned short port = kDefaultPort;
6914 WRITE_LOG("Mocking region with \"or-wa\"");
6915 CMockString mock(*g_LBOS_UnitTesting_CurrentDomain(), "or-wa");
6916 result = s_DeannounceC(node_name.c_str(), "1.0.0", "", port,
6917 &lbos_answer.Get(), &lbos_status_message.Get());
6918 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_LbosNotFound);
6919 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
6920 "LBOS status message is not NULL");
6921 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
6922 "Answer from LBOS was not NULL");
6923 /* Cleanup*/
6924 WRITE_LOG("Reverting mock of region with \"or-wa\"");
6925 }
6926 #endif
6927 }
6928
6929
6930 /* 7. Deannounce without IP specified - deannounce from local host */
6931 /* Test is NOT thread-safe. */
6932 /* NOT ON WINDOWS. */
NoHostProvided__LocalAddress()6933 void NoHostProvided__LocalAddress()
6934 {
6935 WRITE_LOG("Deannounce without IP specified - deannounce from local host");
6936 CLBOSStatus lbos_status(true, true);
6937 unsigned short result;
6938 CCObjHolder<char> lbos_answer(NULL);
6939 CCObjHolder<char> lbos_status_message(NULL);
6940 string node_name = s_GenerateNodeName();
6941 unsigned short port = kDefaultPort;
6942 stringstream healthcheck;
6943 healthcheck << ":4097/healt" << "?port=" << port <<
6944 "&host=" << "cnn.com" << "&version=" << "1.0.0";
6945 /* Prepare for test. We need to be sure that there is no previously
6946 * registered non-deleted service. We count server with chosen port
6947 * and check if there is no server already announced */
6948 int count_before;
6949 SELECT_PORT(count_before, node_name, port);
6950 s_AnnounceCSafe(node_name.c_str(), "1.0.0", "", port,
6951 ("http://" ANNOUNCEMENT_HOST_0000 ":" +
6952 s_PortStr(PORT_N) + "/health").c_str(), "",
6953 &lbos_answer.Get(), &lbos_status_message.Get());
6954 lbos_answer = NULL;
6955 lbos_status_message = NULL;
6956 healthcheck.str(std::string());
6957 healthcheck << ":" + s_PortStr(PORT_N) + "/health" << "?port=" << port <<
6958 "&host=" << "" << "&version=1.0.0";
6959 bool is_announced = s_CheckIfAnnounced(node_name, "1.0.0", port,
6960 healthcheck.str().c_str(),
6961 true);
6962 NCBITEST_CHECK_EQUAL_MT_SAFE(is_announced, true);
6963 result =
6964 s_DeannounceC(node_name.c_str(), "1.0.0", NULL, port,
6965 &lbos_answer.Get(), &lbos_status_message.Get());
6966 is_announced = s_CheckIfAnnounced(node_name, "1.0.0", port,
6967 ":" + s_PortStr(PORT_N) + "/health",
6968 false);
6969 NCBITEST_CHECK_EQUAL_MT_SAFE(is_announced, false);
6970 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_Success);
6971 NCBITEST_CHECK_EQUAL_MT_SAFE(
6972 string(*lbos_status_message ? *lbos_status_message : "<NULL>"), "OK");
6973 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
6974 "Answer from LBOS was not NULL");
6975 }
6976
6977
6978 /* 8. LBOS is OFF - return eLBOS_Disabled */
6979 /* Test is NOT thread-safe. */
LBOSOff__ReturnKLBOSOff()6980 void LBOSOff__ReturnKLBOSOff()
6981 {
6982 WRITE_LOG("Deannonce when LBOS mapper is OFF - return eLBOS_Disabled");
6983 CLBOSStatus lbos_status(true, false);
6984 CCObjHolder<char> lbos_answer(NULL);
6985 CCObjHolder<char> lbos_status_message(NULL);
6986 unsigned short result =
6987 s_DeannounceC("lbostest", "1.0.0", "", 8080,
6988 &lbos_answer.Get(), &lbos_status_message.Get());
6989 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_Disabled);
6990 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_status_message == NULL,
6991 "LBOS status message is not NULL");
6992 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
6993 "Answer from LBOS was not NULL");
6994 }
6995 /* 9. Trying to deannounce non-existent service - return eLbosNotFound */
6996 /* Test is thread-safe. */
NotExists__ReturnKLBOSNotFound()6997 void NotExists__ReturnKLBOSNotFound()
6998 {
6999 WRITE_LOG("Deannonce non-existent service - return eLbosNotFound");
7000 CLBOSStatus lbos_status(true, true);
7001 CCObjHolder<char> lbos_answer(NULL);
7002 CCObjHolder<char> lbos_status_message(NULL);
7003 unsigned short result =
7004 s_DeannounceC("notexists", "1.0.0",
7005 "", 8080,
7006 &lbos_answer.Get(), &lbos_status_message.Get());
7007 NCBITEST_CHECK_EQUAL_MT_SAFE(result, eLBOS_NotFound);
7008 NCBITEST_CHECK_EQUAL_MT_SAFE(
7009 string(*lbos_status_message ? *lbos_status_message : "<NULL>"),
7010 "Not Found");
7011 NCBITEST_CHECK_MESSAGE_MT_SAFE(*lbos_answer == NULL,
7012 "Answer from LBOS was not NULL");
7013 }
7014 }
7015 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
7016 namespace DeannouncementAll
7017 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
7018 {
7019 /* 1. If function was called and no servers were announced after call, no
7020 announced servers should be found in LBOS.
7021 No multithread! */
AllDeannounced__NoSavedLeft()7022 void AllDeannounced__NoSavedLeft()
7023 {
7024 WRITE_LOG("DeannonceAll - should deannounce everyrithing that was announced");
7025 CLBOSStatus lbos_status(true, true);
7026 CCObjHolder<char> lbos_answer(NULL);
7027 CCObjHolder<char> lbos_status_message(NULL);
7028 /* First, announce some random servers */
7029 vector<unsigned short> ports, counts_before, counts_after;
7030 unsigned int i = 0;
7031 string node_name = s_GenerateNodeName();
7032 unsigned short port = kDefaultPort;
7033 WRITE_LOG("Part I. Announcing");
7034 for (i = 0; i < 10; i++) {
7035 int count_before;
7036 SELECT_PORT(count_before, node_name, port);
7037 ports.push_back(port);
7038 counts_before.push_back(count_before);
7039 s_AnnounceCSafe(node_name.c_str(), "1.0.0", "", ports[i],
7040 ("http://" ANNOUNCEMENT_HOST_0000 ":" +
7041 s_PortStr(PORT_N) + "/health").c_str(), "",
7042 &lbos_answer.Get(), &lbos_status_message.Get());
7043 lbos_answer = NULL;
7044 lbos_status_message = NULL;
7045 }
7046 WRITE_LOG("Part II. DeannounceAll");
7047 s_DeannounceAll();
7048
7049 WRITE_LOG("Part III. Checking discovery - should find nothing");
7050 for (i = 0; i < ports.size(); i++) {
7051 counts_after.push_back(
7052 s_CountServersWithExpectation(
7053 s_GenerateNodeName(), ports[i], counts_before[i], __LINE__,
7054 kDiscoveryDelaySec));
7055 NCBITEST_CHECK_EQUAL_MT_SAFE(counts_before[i], counts_after[i]);
7056 }
7057 }
7058 }
7059
7060
7061
7062 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
7063 namespace Announcement_CXX
7064 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
7065 {
7066
7067 /* 1. Successfully announced : return SUCCESS */
7068 /* Test is thread-safe. */
AllOK__ReturnSuccess()7069 void AllOK__ReturnSuccess()
7070 {
7071 CLBOSStatus lbos_status(true, true);
7072 string lbos_answer;
7073 string node_name = s_GenerateNodeName();
7074 unsigned short port = kDefaultPort;
7075 WRITE_LOG("Testing simple announce test. Should return 200.");
7076 /* Prepare for test. We need to be sure that there is no previously
7077 * registered non-deleted service. We count server with chosen port
7078 * and check if there is no server already announced */
7079 int count_before;
7080 SELECT_PORT(count_before, node_name, port);
7081 /*
7082 * I. Check with 0.0.0.0
7083 */
7084 WRITE_LOG("Part I : 0.0.0.0");
7085 BOOST_CHECK_NO_THROW(s_AnnounceCPPSafe(node_name, "1.0.0", "", port,
7086 "http://" ANNOUNCEMENT_HOST_0000 ":"
7087 + s_PortStr(PORT_N) +
7088 "/health"));
7089 /* Cleanup */
7090 BOOST_CHECK_NO_THROW(s_DeannounceCPP(node_name, "1.0.0", "", port));
7091
7092 /* Now check with IP instead of host name */
7093 /*
7094 * II. Now check with IP
7095 */
7096 WRITE_LOG("Part II: real IP");
7097 node_name = s_GenerateNodeName();
7098 SELECT_PORT(count_before, node_name, port);
7099 string health = string("http://") + ANNOUNCEMENT_HOST + ":8080/health";
7100 BOOST_CHECK_NO_THROW(s_AnnounceCPPSafe(node_name, "1.0.0", "", port,
7101 health));
7102 /* Count how many servers there are */
7103 /* Cleanup */
7104 BOOST_CHECK_NO_THROW(s_DeannounceCPP(node_name, "1.0.0", s_GetMyIP(),
7105 port));
7106 }
7107
7108
7109 /* 4. Successfully announced: information about announcement is saved to
7110 * hidden LBOS mapper's storage */
7111 /* Test is thread-safe. */
AllOK__AnnouncedServerSaved()7112 void AllOK__AnnouncedServerSaved()
7113 {
7114 WRITE_LOG("Testing saving of parameters of announced server when "
7115 "announcement finished successfully");
7116 CLBOSStatus lbos_status(true, true);
7117 /* Prepare for test. We need to be sure that there is no previously
7118 * registered non-deleted service */
7119 string node_name = s_GenerateNodeName();
7120 unsigned short port = kDefaultPort;
7121 /* Prepare for test. We need to be sure that there is no previously
7122 * registered non-deleted service. We count server with chosen port
7123 * and check if there is no server already announced */
7124 int count_before;
7125 WRITE_LOG("Part I : 0.0.0.0");
7126 SELECT_PORT(count_before, node_name, port);
7127 BOOST_CHECK_NO_THROW(s_AnnounceCPPSafe(node_name, "1.0.0", "", port,
7128 "http://" ANNOUNCEMENT_HOST_0000 ":" +
7129 s_PortStr(PORT_N) + "/health"));
7130 int find_result = s_FindAnnouncedServer(node_name.c_str(), "1.0.0", port,
7131 "0.0.0.0");
7132 NCBITEST_CHECK_NE_MT_SAFE(find_result, -1);
7133 /* Cleanup */
7134 BOOST_CHECK_NO_THROW(s_DeannounceCPP(node_name, "1.0.0",
7135 "", port));
7136 /* Now check with IP instead of host name */
7137 WRITE_LOG("Part II: real IP");
7138 node_name = s_GenerateNodeName();
7139 SELECT_PORT(count_before, node_name, port);
7140 BOOST_CHECK_NO_THROW(s_AnnounceCPPSafe(node_name, "1.0.0", "", port,
7141 string("http://") +
7142 ANNOUNCEMENT_HOST + ":8080/health"));
7143 find_result = s_FindAnnouncedServer(node_name.c_str(), "1.0.0",
7144 port, s_GetMyIP().c_str());
7145 NCBITEST_CHECK_NE_MT_SAFE(find_result, -1);
7146 /* Cleanup */
7147 BOOST_CHECK_NO_THROW(s_DeannounceCPP(node_name, "1.0.0", "", port));
7148 }
7149
7150
7151 /* 5. Could not find LBOS: throw exception NO_LBOS */
7152 /* Test is NOT thread-safe. */
NoLBOS__ThrowNoLBOSAndNotFind()7153 void NoLBOS__ThrowNoLBOSAndNotFind()
7154 {
7155 WRITE_LOG("Testing behavior of LBOS when no LBOS is found.");
7156 WRITE_LOG("Expected exception with error code \"" << "eLbosNotFound" <<
7157 "\", status code \"" << 450 <<
7158 "\", message \"" << "450\\n" << "\".");
7159 ExceptionComparator<CLBOSException::eLbosNotFound, 450> comparator("450\n");
7160 CLBOSStatus lbos_status(true, true);
7161 string node_name = s_GenerateNodeName();
7162 unsigned short port = kDefaultPort;
7163 WRITE_LOG("Mocking CONN_Read() with s_FakeReadEmpty()");
7164 CMockFunction<FLBOS_ConnReadMethod*> mock(
7165 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
7166 s_FakeReadEmpty);
7167 BOOST_CHECK_EXCEPTION(s_AnnounceCPP(node_name, "1.0.0", "", port,
7168 "http://" ANNOUNCEMENT_HOST_0000 ":" +
7169 s_PortStr(PORT_N) + "/health"),
7170 CLBOSException, comparator);
7171
7172 /* Cleanup*/
7173 WRITE_LOG("Reverting mock of CONN_Read() with s_FakeReadEmpty()");
7174 }
7175
7176
7177 /* 8. LBOS returned unknown error: return its code */
7178 /* Test is NOT thread-safe. */
LBOSError__ThrowServerError()7179 void LBOSError__ThrowServerError()
7180 {
7181 WRITE_LOG("LBOS returned unknown error: "
7182 "Should throw exception with received code (507)");
7183 WRITE_LOG("Expected exception with error code \"" << "eUnknown" <<
7184 "\", status code \"" << 507 <<
7185 "\", message \"" <<
7186 "507 LBOS STATUS Those lbos errors are scaaary\\n" << "\".");
7187 ExceptionComparator<CLBOSException::eUnknown, 507> comparator(
7188 "507 LBOS STATUS Those lbos errors are scaaary\n");
7189 CLBOSStatus lbos_status(true, true);
7190 string node_name = s_GenerateNodeName();
7191 unsigned short port = kDefaultPort;
7192 CMockFunction<FLBOS_ConnReadMethod*> mock(
7193 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
7194 s_FakeReadAnnouncementWithErrorFromLBOS);
7195 BOOST_CHECK_EXCEPTION(s_AnnounceCPP(node_name, "1.0.0", "", port,
7196 "http://" ANNOUNCEMENT_HOST_0000 ":" +
7197 s_PortStr(PORT_N) + "/health"),
7198 CLBOSException, comparator);
7199 }
7200
7201
7202 /* 9. LBOS returned error : char* lbos_answer contains answer of LBOS */
7203 /* Test is NOT thread-safe. */
LBOSError__LBOSAnswerProvided()7204 void LBOSError__LBOSAnswerProvided()
7205 {
7206 WRITE_LOG("LBOS returned unknown error: "
7207 " Exact message from LBOS should be provided");
7208 WRITE_LOG("Expected exception with error code \"" << "eUnknown" <<
7209 "\", status code \"" << 507 <<
7210 "\", message \"" <<
7211 "507 LBOS STATUS Those lbos errors are scaaary\\n" << "\".");
7212 CLBOSStatus lbos_status(true, true);
7213 string node_name = s_GenerateNodeName();
7214 unsigned short port = kDefaultPort;
7215 CMockFunction<FLBOS_ConnReadMethod*> mock(
7216 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
7217 s_FakeReadAnnouncementWithErrorFromLBOS);
7218 try {
7219 s_AnnounceCPP(node_name, "1.0.0", "", port,
7220 "http://" ANNOUNCEMENT_HOST_0000 ":" +
7221 s_PortStr(PORT_N) + "/health");
7222 }
7223 catch(const CLBOSException& ex) {
7224 /* Checking that message in exception is exactly what LBOS sent*/
7225 NCBITEST_CHECK_MESSAGE_MT_SAFE(
7226 ex.GetErrCode() == CLBOSException::eUnknown,
7227 "LBOS exception contains wrong error type");
7228 const char* ex_message =
7229 strstr(ex.what(), "Error: ") + strlen("Error: ");
7230 string message = "";
7231 message.append(ex_message);
7232 NCBITEST_CHECK_EQUAL_MT_SAFE(
7233 message, string("507 LBOS STATUS Those lbos errors are scaaary\n"));
7234 return;
7235 }
7236 catch (...) {
7237 NCBITEST_CHECK_MESSAGE_MT_SAFE(false, "Wrong exception was generated");
7238 return;
7239 }
7240 NCBITEST_CHECK_MESSAGE_MT_SAFE(false, "No exception was generated");
7241 }
7242
7243
7244 /* 11. Server announced again(service name, IP and port coincide) and
7245 * announcement in the same zone, replace old info about announced
7246 * server in internal storage with new one. */
7247 /* Test is thread-safe. */
AlreadyAnnouncedInTheSameZone__ReplaceInStorage()7248 void AlreadyAnnouncedInTheSameZone__ReplaceInStorage()
7249 {
7250 WRITE_LOG("Testing behavior of LBOS "
7251 "mapper when server was already announced (info stored in "
7252 "internal storage should be replaced. Server node should be "
7253 "rewritten, no duplicates.");
7254 CLBOSStatus lbos_status(true, true);
7255 string node_name = s_GenerateNodeName();
7256 unsigned short port = kDefaultPort;
7257 /* Prepare for test. We need to be sure that there is no previously
7258 * registered non-deleted service. We count server with chosen port
7259 * and check if there is no server already announced */
7260 int count_before;
7261 SELECT_PORT(count_before, node_name, port);
7262 /*
7263 * First time
7264 */
7265 WRITE_LOG("Part 1. First time announcing server");
7266 BOOST_CHECK_NO_THROW(s_AnnounceCPPSafe(node_name, "1.0.0", "", port,
7267 "http://" ANNOUNCEMENT_HOST_0000 ":"
7268 + s_PortStr(PORT_N) + "/health"));
7269 /* Count how many servers there are */
7270 int count_after = s_CountServersWithExpectation(node_name, port, 1,
7271 __LINE__,
7272 kDiscoveryDelaySec);
7273 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after, count_before + 1);
7274 int find_result = s_FindAnnouncedServer(node_name, "1.0.0", port,
7275 "0.0.0.0");
7276 NCBITEST_CHECK_EQUAL_MT_SAFE(find_result, 1);
7277 /*
7278 * Second time
7279 */
7280 WRITE_LOG("Part 2. Second time announcing server");
7281 BOOST_CHECK_NO_THROW(
7282 s_AnnounceCPPSafe(node_name, "1.0.0", "", port,
7283 "http://" ANNOUNCEMENT_HOST_0000 ":" +
7284 s_PortStr(PORT_N) + "/health"));
7285 /* Count how many servers there are. */
7286 count_after = s_CountServersWithExpectation(node_name, port, 1, __LINE__,
7287 kDiscoveryDelaySec);
7288 find_result = s_FindAnnouncedServer(node_name, "1.0.0", port,
7289 "0.0.0.0");
7290 NCBITEST_CHECK_EQUAL_MT_SAFE(find_result, 1);
7291 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after, count_before + 1);
7292 /* Cleanup */
7293 BOOST_CHECK_NO_THROW(s_DeannounceCPP(node_name, "1.0.0", "", port));
7294 }
7295
7296
7297 /* 13. Was passed incorrect healthcheck URL (empty, not starting with
7298 * "http(s)://") : do not announce and return INVALID_ARGS */
7299 /* Test is thread-safe. */
IncorrectURL__ThrowInvalidArgs()7300 void IncorrectURL__ThrowInvalidArgs()
7301 {
7302 ExceptionComparator<CLBOSException::eInvalidArgs, 452>
7303 comparator ("452\n");
7304 CLBOSStatus lbos_status(true, true);
7305 string node_name = s_GenerateNodeName();
7306 unsigned short port = kDefaultPort;
7307 WRITE_LOG("Testing behavior of LBOS "
7308 "mapper when passed incorrect healthcheck URL");
7309 WRITE_LOG("Expected exception with error code \"" << "eInvalidArgs" <<
7310 "\", status code \"" << 452 <<
7311 "\", message \"" << "452\\n" << "\".");
7312 /* Count how many servers there are before we announce */
7313 /*
7314 * I. Healthcheck URL that does not start with http or https
7315 */
7316 WRITE_LOG("Part I. Healthcheck is <NULL>");
7317 port = kDefaultPort;
7318 node_name = s_GenerateNodeName();
7319 BOOST_CHECK_EXCEPTION(
7320 s_AnnounceCPP(node_name, "1.0.0", "", port, "0.0.0.0:8080/health"),
7321 CLBOSException, comparator);
7322 /*
7323 * II. Empty healthcheck URL
7324 */
7325 WRITE_LOG("Part II. Healthcheck is \"\" (empty string)");
7326 port = kDefaultPort;
7327 node_name = s_GenerateNodeName();
7328 BOOST_CHECK_EXCEPTION(
7329 s_AnnounceCPP(node_name, "1.0.0", "", port, ""),
7330 CLBOSException, comparator);
7331 }
7332
7333
7334 /* 14. Was passed incorrect port(zero) : do not announce and return
7335 * INVALID_ARGS */
7336 /* Test is thread-safe. */
IncorrectPort__ThrowInvalidArgs()7337 void IncorrectPort__ThrowInvalidArgs()
7338 {
7339 WRITE_LOG("Testing behavior of LBOS "
7340 "mapper when passed incorrect port (zero)");
7341 WRITE_LOG("Expected exception with error code \"" << "eInvalidArgs" <<
7342 "\", status code \"" << 452 <<
7343 "\", message \"" << "452\\n" << "\".");
7344 ExceptionComparator<CLBOSException::eInvalidArgs, 452>
7345 comparator ("452\n");
7346 CLBOSStatus lbos_status(true, true);
7347 string node_name = s_GenerateNodeName();
7348 unsigned short port = kDefaultPort;
7349 /* Prepare for test. We need to be sure that there is no previously
7350 * registered non-deleted service. We count server with chosen port
7351 * and check if there is no server already announced */
7352 int count_before;
7353 SELECT_PORT(count_before, node_name, port);
7354 /* Count how many servers there are before we announce */
7355 BOOST_CHECK_EXCEPTION(
7356 s_AnnounceCPP(node_name, "1.0.0", "", 0,
7357 "http://0.0.0.0:8080/health"), CLBOSException, comparator);
7358 }
7359
7360
7361 /* 15. Was passed incorrect version(empty) : do not announce and
7362 * return INVALID_ARGS */
7363 /* Test is thread-safe. */
IncorrectVersion__ThrowInvalidArgs()7364 void IncorrectVersion__ThrowInvalidArgs()
7365 {
7366 WRITE_LOG("Testing behavior of LBOS "
7367 "mapper when passed incorrect version - should return "
7368 "eLBOS_InvalidArgs");
7369 WRITE_LOG("Expected exception with error code \"" << "eInvalidArgs" <<
7370 "\", status code \"" << 452 <<
7371 "\", message \"" << "452\\n" << "\".");
7372 ExceptionComparator<CLBOSException::eInvalidArgs, 452>
7373 comparator ("452\n");
7374 CLBOSStatus lbos_status(true, true);
7375 string node_name = s_GenerateNodeName();
7376 unsigned short port = kDefaultPort;
7377 node_name = s_GenerateNodeName();
7378 WRITE_LOG("Version is \"\" (empty string)");
7379 /*
7380 * I. Empty string
7381 */
7382 string health = "http://" ANNOUNCEMENT_HOST_0000 ":" +
7383 s_PortStr(PORT_N) + "/health";
7384 stringstream healthcheck;
7385 healthcheck << health << "/port" << port << "/host" << "" <<
7386 "/version" << "";
7387 BOOST_CHECK_EXCEPTION(
7388 LBOS::Announce(node_name, "", "", port,
7389 healthcheck.str()),
7390 CLBOSException, comparator);
7391 }
7392
7393
7394 /* 16. Was passed incorrect service name (empty): do not
7395 * announce and return INVALID_ARGS */
7396 /* Test is thread-safe. */
IncorrectServiceName__ThrowInvalidArgs()7397 void IncorrectServiceName__ThrowInvalidArgs()
7398 {
7399 ExceptionComparator<CLBOSException::eInvalidArgs, 452>
7400 comparator ("452\n");
7401 CLBOSStatus lbos_status(true, true);
7402 string node_name = s_GenerateNodeName();
7403 unsigned short port = kDefaultPort;
7404 WRITE_LOG("Testing behavior of LBOS "
7405 "mapper when passed incorrect service name - should return "
7406 "eLBOS_InvalidArgs");
7407 WRITE_LOG("Expected exception with error code \"" << "eInvalidArgs" <<
7408 "\", status code \"" << 452 <<
7409 "\", message \"" << "452\\n" << "\".");
7410 /*
7411 * I. Empty service name
7412 */
7413 WRITE_LOG("Service name is \"\" (empty string)");
7414 node_name = s_GenerateNodeName();
7415 port = kDefaultPort;
7416 /* As the call is not supposed to go through mapper to network,
7417 * we do not need any mocks*/
7418 BOOST_CHECK_EXCEPTION(
7419 s_AnnounceCPP("", "1.0.0", "", port,
7420 "http://" ANNOUNCEMENT_HOST_0000 ":" + s_PortStr(PORT_N) +
7421 "/health"), CLBOSException, comparator);
7422 }
7423
7424
7425 /* 17. Real - life test : after announcement server should be visible to
7426 * resolve */
7427 /* Test is thread-safe. */
RealLife__VisibleAfterAnnounce()7428 void RealLife__VisibleAfterAnnounce()
7429 {
7430 CLBOSStatus lbos_status(true, true);
7431 unsigned short port = kDefaultPort;
7432 string node_name = s_GenerateNodeName();
7433 WRITE_LOG("Real-life test of LBOS: "
7434 "after announcement, number of servers with specific name, "
7435 "port and version should increase by 1");
7436 /* Prepare for test. We need to be sure that there is no previously
7437 * registered non-deleted service. We count server with chosen port
7438 * and check if there is no server already announced */
7439 int count_before;
7440 SELECT_PORT(count_before, node_name, port);
7441 BOOST_CHECK_NO_THROW(
7442 s_AnnounceCPPSafe(node_name, "1.0.0", "", port,
7443 "http://" ANNOUNCEMENT_HOST_0000 ":" +
7444 s_PortStr(PORT_N) + "/health"));
7445 int count_after = s_CountServersWithExpectation(node_name, port, 1,
7446 __LINE__,
7447 kDiscoveryDelaySec);
7448 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after, count_before + 1);
7449 /* Cleanup */
7450 BOOST_CHECK_NO_THROW(s_DeannounceCPP(node_name, "1.0.0", "", port));
7451 }
7452
7453
7454 /* 18. If was passed "0.0.0.0" as IP, we change 0.0.0.0 to real IP */
7455 /* Test is NOT thread-safe. */
IP0000__ReplaceWithIP()7456 void IP0000__ReplaceWithIP()
7457 {
7458 ExceptionComparator<CLBOSException::eDNSResolve, 451>
7459 comparator ("451\n");
7460 CLBOSStatus lbos_status(true, true);
7461 /* Here we mock SOCK_gethostbyaddrEx to specify IP address that we want to
7462 * expect in place of "0.0.0.0" */
7463 string node_name = s_GenerateNodeName();
7464 unsigned short port = kDefaultPort;
7465 WRITE_LOG("If healthcheck has 0.0.0.0 specified as host: "
7466 "it should be sent as-is to LBOS");
7467 WRITE_LOG("Mocking SOCK_gethostbyaddr with \"1.2.3.4\"");
7468 CMockFunction<FLBOS_SOCKGetLocalHostAddressMethod*> mock1(
7469 g_LBOS_UnitTesting_GetLBOSFuncs()->LocalHostAddr,
7470 s_FakeGetLocalHostAddress<true, 1, 2, 3, 4>);
7471 WRITE_LOG("Mocking Announce with fake Anonounce");
7472 CMockFunction<FLBOS_AnnounceMethod*> mock2 (
7473 g_LBOS_UnitTesting_GetLBOSFuncs()->AnnounceEx,
7474 s_FakeAnnounceEx);
7475 BOOST_CHECK_EXCEPTION(
7476 s_AnnounceCPP(node_name, "1.0.0", "", port,
7477 "http://" ANNOUNCEMENT_HOST_0000 ":" + s_PortStr(PORT_N) +
7478 "/health"), CLBOSException, comparator);
7479 stringstream healthcheck;
7480 healthcheck << "http%3A%2F%2F1.2.3.4%3A" + s_PortStr(PORT_N) + "%2Fhealth" <<
7481 "%2Fport" << port <<
7482 "%2Fhost" << "" << "%2Fversion1.0.0";
7483 NCBITEST_CHECK_EQUAL_MT_SAFE(s_LBOS_hostport, healthcheck.str().c_str());
7484 mock1 = s_FakeGetLocalHostAddress<true, 251,252,253,147>;
7485 BOOST_CHECK_EXCEPTION(
7486 s_AnnounceCPP(node_name, "1.0.0", "", port,
7487 "http://" ANNOUNCEMENT_HOST_0000 ":" + s_PortStr(PORT_N) +
7488 "/health"), CLBOSException, comparator);
7489 healthcheck.str(std::string());
7490 healthcheck << "http%3A%2F%2F251.252.253.147%3A" + s_PortStr(PORT_N) +
7491 "%2Fhealth" <<
7492 "%2Fport" << port <<
7493 "%2Fhost" << "" << "%2Fversion1.0.0";
7494 NCBITEST_CHECK_EQUAL_MT_SAFE(s_LBOS_hostport, healthcheck.str().c_str());
7495 /* Cleanup*/
7496 WRITE_LOG("Reverting mock og SOCK_gethostbyaddr with \"1.2.3.4\"");
7497 WRITE_LOG("Reverting mock of Announce with fake Anonounce");
7498 }
7499
7500
7501 /* 19. Was passed "0.0.0.0" as IP and could not manage to resolve local host
7502 * IP - do not announce and return DNS_RESOLVE_ERROR */
7503 /* Test is NOT thread-safe. */
ResolveLocalIPError__ReturnDNSError()7504 void ResolveLocalIPError__ReturnDNSError()
7505 {
7506 ExceptionComparator<CLBOSException::eDNSResolve, 451>
7507 comparator("451\n");
7508 CLBOSStatus lbos_status(true, true);
7509 WRITE_LOG("If healthcheck has 0.0.0.0 specified as host, "
7510 "and running SOCK_gethostbyaddr returns error: "
7511 "do not care, because we do not substitute 0.0.0.0, "
7512 "we send it as it is");
7513 /* Here we mock SOCK_gethostbyaddrEx to know IP address that we want to
7514 * expect in place of "0.0.0.0" */
7515 string node_name = s_GenerateNodeName();
7516 unsigned short port = kDefaultPort;
7517 WRITE_LOG("Mocking SOCK_gethostbyaddr with \"0.0.0.0\"");
7518 CMockFunction<FLBOS_SOCKGetLocalHostAddressMethod*> mock(
7519 g_LBOS_UnitTesting_GetLBOSFuncs()->LocalHostAddr,
7520 s_FakeGetLocalHostAddress<false,0,0,0,0>);
7521 BOOST_CHECK_EXCEPTION(
7522 s_AnnounceCPP(node_name, "1.0.0", "", port,
7523 "http://" ANNOUNCEMENT_HOST_0000 ":" + s_PortStr(PORT_N) +
7524 "/health"), CLBOSException, comparator);
7525 /* Cleanup*/
7526 WRITE_LOG("Reverting mock og SOCK_gethostbyaddr with \"0.0.0.0\"");
7527 }
7528
7529 /* 20. LBOS is OFF - return eLBOS_Disabled */
LBOSOff__ThrowKLBOSOff()7530 void LBOSOff__ThrowKLBOSOff()
7531 {
7532 ExceptionComparator<CLBOSException::eDisabled, 550>
7533 comparator("550\n");
7534 CLBOSStatus lbos_status(true, false);
7535 WRITE_LOG("LBOS mapper is OFF (maybe it is not turned ON in registry "
7536 "or it could not initialize at start) - return eLBOS_Disabled");
7537 WRITE_LOG("Expected exception with error code \"" << "eDisabled" <<
7538 "\", status code \"" << 550 <<
7539 "\", message \"" << "550\\n" << "\".");
7540 BOOST_CHECK_EXCEPTION(
7541 s_AnnounceCPP("lbostest", "1.0.0", "", 8080,
7542 "http://" ANNOUNCEMENT_HOST_0000 ":" + s_PortStr(PORT_N) +
7543 "/health"),
7544 CLBOSException, comparator);
7545 }
7546
7547
7548 /*21. Announced successfully, but LBOS return corrupted answer -
7549 return 454 and exact answer of LBOS */
LBOSAnnounceCorruptOutput__ThrowServerError()7550 void LBOSAnnounceCorruptOutput__ThrowServerError()
7551 {
7552 ExceptionComparator<CLBOSException::eProtocol, 454>
7553 comparator ("454 Corrupt output\n");
7554 WRITE_LOG("Announced successfully, but LBOS returns corrupted answer.");
7555 WRITE_LOG("Expected exception with error code \"" <<
7556 "eProtocol" <<
7557 "\", status code \"" << 454 <<
7558 "\", message \"" << "454 Corrupt output\\n" << "\".");
7559 CLBOSStatus lbos_status(true, true);
7560 string node_name = s_GenerateNodeName();
7561 unsigned short port = kDefaultPort;
7562 WRITE_LOG("Mocking CONN_Read with corrupt output");
7563 CMockFunction<FLBOS_ConnReadMethod*> mock(
7564 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
7565 s_FakeReadAnnouncementSuccessWithCorruptOutputFromLBOS);
7566 BOOST_CHECK_EXCEPTION(
7567 s_AnnounceCPP(node_name, "1.0.0", "", port,
7568 "http://" ANNOUNCEMENT_HOST_0000 ":" + s_PortStr(PORT_N) +
7569 "/health"), CLBOSException, comparator);
7570 /* Cleanup */
7571 WRITE_LOG("Reverting mock of CONN_Read with corrupt output");
7572 }
7573
7574
7575 /*22. Trying to announce server and providing dead healthcheck URL -
7576 return eLbosNotFound */
HealthcheckDead__ThrowE_NotFound()7577 void HealthcheckDead__ThrowE_NotFound()
7578 {
7579 CLBOSStatus lbos_status(true, true);
7580 CCObjHolder<char> lbos_answer(NULL);
7581 string node_name = s_GenerateNodeName();
7582 unsigned short port = kDefaultPort;
7583 int count_before;
7584 WRITE_LOG("Trying to announce server providing dead healthcheck URL - "
7585 "return code from LBOS(200). If healthcheck is at non - existent "
7586 "domain - throw exception");
7587 /*
7588 * I. Healthcheck is on non-existent domain
7589 */
7590 WRITE_LOG("Part I. Healthcheck is \"http://badhealth.gov\" - "
7591 "return eLBOS_BadRequest");
7592 SELECT_PORT(count_before, node_name, port);
7593 WRITE_LOG("Expected exception with error code \"" <<
7594 "eBadRequest" <<
7595 "\", status code \"" << 400 <<
7596 "\", message \"" << "400 Bad Request\\n" << "\".");
7597 ExceptionComparator<CLBOSException::eBadRequest, 400>
7598 comparator("400 Bad Request\n");
7599 BOOST_CHECK_EXCEPTION(
7600 s_AnnounceCPP(node_name, "1.0.0", "", port, "http://badhealth.gov"),
7601 CLBOSException, comparator);
7602 int count_after = s_CountServersWithExpectation(node_name, port, 0,
7603 __LINE__,
7604 kDiscoveryDelaySec);
7605 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after - count_before, 0);
7606 count_after = s_CountServersWithExpectation(node_name, port, 0, __LINE__,
7607 kDiscoveryDelaySec);
7608 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after - count_before, 0);
7609
7610 /*
7611 * II. Healthcheck returns 404
7612 */
7613 WRITE_LOG("Part II. Healthcheck is \"http:/0.0.0.0:4097/healt\" - "
7614 "should work fine");
7615 SELECT_PORT(count_before, node_name, port);
7616 BOOST_CHECK_NO_THROW( // missing 'h'
7617 s_AnnounceCPPSafe(node_name, "1.0.0", "", port,// v
7618 "http://" ANNOUNCEMENT_HOST_0000 ":" +
7619 s_PortStr(PORT_N) + "/healt"));
7620 count_after = s_CountServersWithExpectation(node_name, port, 0, __LINE__,
7621 kDiscoveryDelaySec);
7622 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after - count_before, 0);
7623 lbos_answer = NULL;
7624 s_DeannounceC(node_name.c_str(), "1.0.0", "cnn.com", port,
7625 &lbos_answer.Get(), NULL);
7626 count_after = s_CountServersWithExpectation(node_name, port, 0, __LINE__,
7627 kDiscoveryDelaySec);
7628 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after - count_before, 0);
7629 }
7630
7631
7632 /*23. Trying to announce server and providing dead healthcheck URL -
7633 server should be announced */
HealthcheckDead__AnnouncementOK()7634 void HealthcheckDead__AnnouncementOK()
7635 {
7636 CLBOSStatus lbos_status(true, true);
7637 string node_name = s_GenerateNodeName();
7638 unsigned short port = kDefaultPort;
7639 WRITE_LOG("Trying to announce server providing dead healthcheck URL - "
7640 "server should be announced");
7641 /* We do not care if announcement throws or not (we check it in other
7642 tests), we check if server is announced */
7643 try {
7644 s_AnnounceCPP(node_name, "1.0.0", "", port, "http://0.0.0.0:8080/healt");
7645 }
7646 catch(...)
7647 {
7648 }
7649 stringstream healthcheck;
7650 healthcheck << ":8080/healt" << "?port=" << port <<
7651 "&host=" << "" << "&version=" << "1.0.0";
7652 bool is_announced = s_CheckIfAnnounced(node_name, "1.0.0", port,
7653 healthcheck.str().c_str());
7654 NCBITEST_CHECK_EQUAL_MT_SAFE(is_announced, true);
7655 }
7656
7657
7658 /* 24. Announce server with separate host and healthcheck - should be found in
7659 * %LBOS%/text/service */
SeparateHost__AnnouncementOK()7660 void SeparateHost__AnnouncementOK()
7661 {
7662 CLBOSStatus lbos_status(true, true);
7663 CCObjHolder<char> lbos_answer(NULL);
7664 string node_name = s_GenerateNodeName();
7665 CCObjHolder<char> lbos_status_message(NULL);
7666 unsigned short port = kDefaultPort;
7667 WRITE_LOG("Trying to announce server with separate host that is not the "
7668 "same as healtcheck host - return code from LBOS(200).");
7669 int count_before;
7670 SELECT_PORT(count_before, node_name, port);
7671
7672 BOOST_CHECK_NO_THROW(s_AnnounceCPPSafe(node_name, "1.0.0", "cnn.com", port,
7673 "http://" ANNOUNCEMENT_HOST_0000 ":"
7674 + s_PortStr(PORT_N) +
7675 "/health"));
7676 int count_after = s_CountServersWithExpectation(node_name, port, 1,
7677 __LINE__,
7678 kDiscoveryDelaySec);
7679 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after, count_before + 1);
7680
7681 stringstream healthcheck;
7682 healthcheck << ":4097/healt" << "?port=" << port <<
7683 "&host=" << "cnn.com" << "&version=1.0.0";
7684 string announced_ip = CLBOSIpCache::HostnameTryFind(node_name, "cnn.com",
7685 "1.0.0", port);
7686 bool is_announced = s_CheckIfAnnounced(node_name, "1.0.0", port,
7687 healthcheck.str().c_str(),
7688 true, announced_ip);
7689 NCBITEST_CHECK_EQUAL_MT_SAFE(is_announced, true);
7690 lbos_answer = NULL;
7691 BOOST_CHECK_NO_THROW(s_DeannounceCPP(node_name.c_str(), "1.0.0",
7692 "cnn.com", port));
7693 }
7694 } /* namespace Announcement */
7695
7696 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
7697 namespace AnnouncementRegistry_CXX /* These tests are NOT for multithreading */
7698 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
7699 {
7700 /* 1. All parameters good (Default section has all parameters correct in
7701 config) - return eLBOS_Success */
ParamsGood__ReturnSuccess()7702 void ParamsGood__ReturnSuccess()
7703 {
7704 WRITE_LOG("Simple announcement from registry. "
7705 "Should work fine");
7706 CLBOSStatus lbos_status(true, true);
7707 BOOST_CHECK_NO_THROW(s_AnnounceCPPFromRegistry(string()));
7708 /* Cleanup */
7709 BOOST_CHECK_NO_THROW(LBOS::DeannounceAll());
7710 }
7711
7712 /* 2. Custom section has nothing in config - return eLBOS_InvalidArgs */
CustomSectionNoVars__ThrowInvalidArgs()7713 void CustomSectionNoVars__ThrowInvalidArgs()
7714 {
7715 ExceptionComparator<CLBOSException::eInvalidArgs, 452>
7716 comparator("Could not parse port \"\" in "
7717 "section \"NON-EXISTENT_SECTION\"\n");
7718 WRITE_LOG("Testing custom section that has nothing in config");
7719 WRITE_LOG("Expected exception with error code \"" <<
7720 "eInvalidArgs" <<
7721 "\", status code \"" << 452 <<
7722 "\", message \"" << "452\\n" << "\".");
7723 CLBOSStatus lbos_status(true, true);
7724 BOOST_CHECK_EXCEPTION(
7725 s_AnnounceCPPFromRegistry("NON-EXISTENT_SECTION"),
7726 CLBOSException, comparator);
7727 }
7728
7729 /* 3. Section empty (should use default section and return
7730 eLBOS_Success, if section is Good) */
CustomSectionEmptyOrNullAndSectionIsOk__AllOK()7731 void CustomSectionEmptyOrNullAndSectionIsOk__AllOK()
7732 {
7733 CLBOSStatus lbos_status(true, true);
7734 WRITE_LOG("Section empty or NULL - should use default section all work "
7735 "fine, if default section is Good");
7736 /*
7737 * Empty section
7738 */
7739 BOOST_CHECK_NO_THROW(s_AnnounceCPPFromRegistry(""));
7740 /* Cleanup */
7741 BOOST_CHECK_NO_THROW(LBOS::DeannounceAll());
7742 }
7743
7744
TestNullOrEmptyField(const char * field_tested)7745 void TestNullOrEmptyField(const char* field_tested)
7746 {
7747 CLBOSStatus lbos_status(true, true);
7748 string empty_section = "SECTION_WITH_EMPTY_";
7749 string field_name = field_tested;
7750 string null_section = "SECTION_WITHOUT_";
7751 ExceptionComparator<CLBOSException::eInvalidArgs, 452>
7752 comparator1(string(field_tested) == "PORT" ?
7753 "Could not parse port \"\" in "
7754 "section \"" + null_section + field_name + "\"\n"
7755 : "452\n");
7756 /*
7757 * I. NULL section
7758 */
7759 WRITE_LOG("Part I. " << field_tested << " is not in section (NULL)");
7760 WRITE_LOG("Expected exception with error code \"" <<
7761 "eInvalidArgs" <<
7762 "\", status code \"" << 452 <<
7763 "\", message \"" << "452\\n" << "\".");
7764 BOOST_CHECK_EXCEPTION(s_AnnounceCPPFromRegistry(null_section + field_name),
7765 CLBOSException, comparator1);
7766 /*
7767 * II. Empty section
7768 */
7769 ExceptionComparator<CLBOSException::eInvalidArgs, 452>
7770 comparator2(string(field_tested) == "PORT" ?
7771 "Could not parse port \"\" in "
7772 "section \"" + empty_section + field_name + "\"\n"
7773 : "452\n");
7774 WRITE_LOG("Part II. " << field_tested << " is an empty string");
7775 WRITE_LOG("Expected exception with error code \"" <<
7776 "eInvalidArgs" <<
7777 "\", status code \"" << 452 <<
7778 "\", message \"" << "452\\n" << "\".");
7779 BOOST_CHECK_EXCEPTION(s_AnnounceCPPFromRegistry(empty_section + field_name),
7780 CLBOSException, comparator2);
7781 }
7782
7783 /* 4. Service is empty or NULL - return eLBOS_InvalidArgs */
ServiceEmptyOrNull__ThrowInvalidArgs()7784 void ServiceEmptyOrNull__ThrowInvalidArgs()
7785 {
7786 WRITE_LOG("Service is empty or NULL");
7787 TestNullOrEmptyField("SERVICE");
7788 }
7789
7790 /* 5. Version is empty or NULL - return eLBOS_InvalidArgs */
VersionEmptyOrNull__ThrowInvalidArgs()7791 void VersionEmptyOrNull__ThrowInvalidArgs()
7792 {
7793 WRITE_LOG("Version is empty or NULL");
7794 TestNullOrEmptyField("VERSION");
7795 }
7796
7797 /* 6. Port is empty or NULL - return eLBOS_InvalidArgs */
PortEmptyOrNull__ThrowInvalidArgs()7798 void PortEmptyOrNull__ThrowInvalidArgs()
7799 {
7800 WRITE_LOG("Service is empty or NULL");
7801 TestNullOrEmptyField("PORT");
7802 }
7803
7804 /* 7. Port is out of range - return eLBOS_InvalidArgs */
PortOutOfRange__ThrowInvalidArgs()7805 void PortOutOfRange__ThrowInvalidArgs()
7806 {
7807 WRITE_LOG("Port is out of range - return eLBOS_InvalidArgs");
7808 /*
7809 * I. port = 0
7810 */
7811 ExceptionComparator<CLBOSException::eInvalidArgs, 452>
7812 comparator1("Invalid server port \"0\" in section "
7813 "\"SECTION_WITH_PORT_OUT_OF_RANGE1\"\n");
7814 WRITE_LOG("Part I. Port is 0");
7815 WRITE_LOG("Expected exception with error code \"" <<
7816 "eInvalidArgs" <<
7817 "\", status code \"" << 452 <<
7818 "\", message \"" << "452\\n" << "\".");
7819 BOOST_CHECK_EXCEPTION(
7820 LBOS::AnnounceFromRegistry("SECTION_WITH_PORT_OUT_OF_RANGE1"),
7821 CLBOSException, comparator1);
7822 /*
7823 * II. port = 100000
7824 */
7825 ExceptionComparator<CLBOSException::eInvalidArgs, 452>
7826 comparator2("Invalid server port \"100000\" in section "
7827 "\"SECTION_WITH_PORT_OUT_OF_RANGE2\"\n");
7828 WRITE_LOG("Part II. Port is 100000");
7829 WRITE_LOG("Expected exception with error code \"" <<
7830 "eInvalidArgs" <<
7831 "\", status code \"" << 452 <<
7832 "\", message \"" << "452\\n" << "\".");
7833 BOOST_CHECK_EXCEPTION(
7834 s_AnnounceCPPFromRegistry("SECTION_WITH_PORT_OUT_OF_RANGE2"),
7835 CLBOSException, comparator2);
7836 /*
7837 * III. port = 65536
7838 */
7839 ExceptionComparator<CLBOSException::eInvalidArgs, 452>
7840 comparator3("Invalid server port \"65536\" in section "
7841 "\"SECTION_WITH_PORT_OUT_OF_RANGE3\"\n");
7842 WRITE_LOG("Part III. Port is 65536");
7843 WRITE_LOG("Expected exception with error code \"" <<
7844 "eInvalidArgs" <<
7845 "\", status code \"" << 452 <<
7846 "\", message \"" << "452\\n" << "\".");
7847 BOOST_CHECK_EXCEPTION(
7848 s_AnnounceCPPFromRegistry("SECTION_WITH_PORT_OUT_OF_RANGE3"),
7849 CLBOSException, comparator3);
7850 }
7851 /* 8. Port contains letters - return eLBOS_InvalidArgs */
PortContainsLetters__ThrowInvalidArgs()7852 void PortContainsLetters__ThrowInvalidArgs()
7853 {
7854 WRITE_LOG("Port contains letters: 152d");
7855 WRITE_LOG("Expected exception with error code \"" <<
7856 "eInvalidArgs" <<
7857 "\", status code \"" << 452 <<
7858 "\", message \"" << "452\\n" << "\".");
7859 ExceptionComparator<CLBOSException::eInvalidArgs, 452>
7860 comparator("Could not parse port \"152d\" in "
7861 "section \"SECTION_WITH_CORRUPTED_PORT\"\n");
7862 CLBOSStatus lbos_status(true, true);
7863 BOOST_CHECK_EXCEPTION(
7864 s_AnnounceCPPFromRegistry("SECTION_WITH_CORRUPTED_PORT"),
7865 CLBOSException, comparator);
7866 }
7867 /* 9. Healthcheck is empty or NULL - return eLBOS_InvalidArgs */
HealthchecktEmptyOrNull__ThrowInvalidArgs()7868 void HealthchecktEmptyOrNull__ThrowInvalidArgs()
7869 {
7870 WRITE_LOG("Healthcheck is empty or NULL");
7871 TestNullOrEmptyField("HEALTHCHECK");
7872 }
7873 /* 10. Healthcheck does not start with http:// or https:// - return
7874 eLBOS_InvalidArgs */
HealthcheckDoesNotStartWithHttp__ThrowInvalidArgs()7875 void HealthcheckDoesNotStartWithHttp__ThrowInvalidArgs()
7876 {
7877 WRITE_LOG("Healthcheck does not start with http:// or https://");
7878 WRITE_LOG("Expected exception with error code \"" <<
7879 "eInvalidArgs" <<
7880 "\", status code \"" << 452 <<
7881 "\", message \"" << "452\\n" << "\".");
7882 ExceptionComparator<CLBOSException::eInvalidArgs, 452>
7883 comparator("452\n");
7884 CLBOSStatus lbos_status(true, true);
7885 BOOST_CHECK_EXCEPTION(
7886 s_AnnounceCPPFromRegistry("SECTION_WITH_CORRUPTED_HEALTHCHECK"),
7887 CLBOSException, comparator);
7888 }
7889 /* 11. Trying to announce server and providing dead healthcheck URL -
7890 return eLbosNotFound */
HealthcheckDead__ThrowE_NotFound()7891 void HealthcheckDead__ThrowE_NotFound()
7892 {
7893 WRITE_LOG("Trying to announce server providing dead healthcheck URL - "
7894 "should be OK");
7895 CLBOSStatus lbos_status(true, true);
7896 unsigned short port = 5001;
7897 string node_name = s_GenerateNodeName();
7898 int count_before;
7899 count_before = s_CountServers(node_name, port);
7900 /* 1. Non-existent domain in healthcheck */
7901 WRITE_LOG("Part I. Healthcheck is \"http://badhealth.gov\" - "
7902 "return eLBOS_BadRequest");
7903 WRITE_LOG("Expected exception with error code \"" <<
7904 "eBadRequest" <<
7905 "\", status code \"" << 400 <<
7906 "\", message \"" << "400 Bad Request\\n" << "\".");
7907 ExceptionComparator<CLBOSException::eBadRequest, 400>
7908 comparator("400 Bad Request\n");
7909 BOOST_CHECK_EXCEPTION(
7910 s_AnnounceCPPFromRegistry("SECTION_WITH_HEALTHCHECK_DNS_ERROR"),
7911 CLBOSException, comparator);
7912 int count_after = s_CountServersWithExpectation(node_name, port, 0,
7913 __LINE__,
7914 kDiscoveryDelaySec);
7915 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after - count_before, 0);
7916 BOOST_CHECK_NO_THROW(LBOS::DeannounceAll());
7917 count_after = s_CountServersWithExpectation(node_name, port, 0, __LINE__,
7918 kDiscoveryDelaySec);
7919 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after - count_before, 0);
7920
7921
7922 /* 2. Healthcheck is reachable but does not answer */
7923 WRITE_LOG("Part II. Healthcheck is \"http:/0.0.0.0:4097/healt\" - "
7924 "return eLBOS_Success");
7925 BOOST_CHECK_NO_THROW(
7926 s_AnnounceCPPFromRegistry("SECTION_WITH_DEAD_HEALTHCHECK"));
7927 count_after = s_CountServersWithExpectation(node_name, port, 0, __LINE__,
7928 kDiscoveryDelaySec);
7929 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after - count_before, 0);
7930 BOOST_CHECK_NO_THROW(LBOS::DeannounceAll());
7931 count_after = s_CountServersWithExpectation(node_name, port, 0, __LINE__,
7932 kDiscoveryDelaySec);
7933 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after - count_before, 0);
7934
7935 /* Cleanup */
7936 BOOST_CHECK_NO_THROW(LBOS::DeannounceAll());
7937 }
7938 }
7939
7940
7941 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
7942 namespace Deannouncement_CXX
7943 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
7944 {
7945 /* 1. Successfully de-announced: return 1 */
7946 /* Test is thread-safe. */
Deannounced__Return1(unsigned short port)7947 void Deannounced__Return1(unsigned short port)
7948 {
7949 WRITE_LOG("Simple deannounce test");
7950 CLBOSStatus lbos_status(true, true);
7951 string node_name = s_GenerateNodeName();
7952 /* Prepare for test. We need to be sure that there is no previously
7953 * registered non-deleted service. We count server with chosen port
7954 * and check if there is no server already announced */
7955 int count_before;
7956 SELECT_PORT(count_before, node_name, port);
7957 /*
7958 * I. Check with 0.0.0.0
7959 */
7960 WRITE_LOG("Part I. 0.0.0.0");
7961 BOOST_CHECK_NO_THROW(
7962 s_AnnounceCPPSafe(node_name, "1.0.0", "", port,
7963 "http://" ANNOUNCEMENT_HOST_0000 ":" + s_PortStr(PORT_N) + "/health"));
7964 /* Count how many servers there are */
7965 int count_after = s_CountServersWithExpectation(node_name, port, 1, __LINE__,
7966 kDiscoveryDelaySec);
7967 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after, count_before + 1);
7968 /* Cleanup */
7969 BOOST_CHECK_NO_THROW(s_DeannounceCPP(node_name, "1.0.0", "", port));
7970 /*
7971 * II. Now check with IP instead of 0.0.0.0
7972 */
7973 WRITE_LOG("Part II. IP");
7974 node_name = s_GenerateNodeName();
7975 SELECT_PORT(count_before, node_name, port);
7976 string health = string("http://") + ANNOUNCEMENT_HOST + ":" +
7977 s_PortStr(PORT_N) + "/health";
7978 BOOST_CHECK_NO_THROW(s_AnnounceCPPSafe(node_name, "1.0.0", "", port,
7979 health));
7980 /* Count how many servers there are */
7981 count_after = s_CountServersWithExpectation(node_name, port, 1, __LINE__,
7982 kDiscoveryDelaySec);
7983 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after, count_before + 1);
7984
7985 BOOST_CHECK_NO_THROW(
7986 s_DeannounceCPP(node_name, "1.0.0", s_GetMyIP(), port));
7987 }
7988
7989
7990 /* 2. Successfully de-announced : if announcement was saved in local storage,
7991 * remove it */
7992 /* Test is thread-safe. */
Deannounced__AnnouncedServerRemoved()7993 void Deannounced__AnnouncedServerRemoved()
7994 {
7995 WRITE_LOG("Successfully de-announced : if announcement was saved in local "
7996 "storage, remove it");
7997 CLBOSStatus lbos_status(true, true);
7998 /* Prepare for test. We need to be sure that there is no previously
7999 * registered non-deleted service */
8000 string node_name = s_GenerateNodeName();
8001 unsigned short port = kDefaultPort;
8002 /* Prepare for test. We need to be sure that there is no previously
8003 * registered non-deleted service. We count server with chosen port
8004 * and check if there is no server already announced */
8005 int count_before;
8006 SELECT_PORT(count_before, node_name, port);
8007 string my_host = s_GetMyHost();
8008 /*
8009 * I. Check with hostname
8010 */
8011 WRITE_LOG("Part I. Check with hostname");
8012 BOOST_CHECK_NO_THROW(
8013 s_AnnounceCPPSafe(node_name, "1.0.0", "", port,
8014 string("http://") + s_GetMyHost() + (":8080/health")));
8015 /* Check that server is in storage */
8016 int find_result = s_FindAnnouncedServer(node_name.c_str(), "1.0.0", port,
8017 s_GetMyIP());
8018 NCBITEST_CHECK_EQUAL_MT_SAFE(find_result, 1);
8019 BOOST_CHECK_NO_THROW(s_DeannounceCPP(node_name, "1.0.0", s_GetMyHost(),
8020 port));
8021 /* Check that server was removed from storage */
8022 find_result = s_FindAnnouncedServer(node_name.c_str(), "1.0.0", port,
8023 s_GetMyIP());
8024 NCBITEST_CHECK_EQUAL_MT_SAFE(find_result, 0);
8025
8026 /* Now check with IP instead of host name */
8027 node_name = s_GenerateNodeName();
8028 SELECT_PORT(count_before, node_name, port);
8029 /*
8030 * II. Now check with IP instead of host name
8031 */
8032 WRITE_LOG("Part II. Check with IP");
8033 BOOST_CHECK_NO_THROW(s_AnnounceCPPSafe(node_name, "1.0.0", "", port,
8034 string("http://") +
8035 ANNOUNCEMENT_HOST +
8036 ":8080/health"));
8037 /* Check that server is in storage */
8038 find_result = s_FindAnnouncedServer(node_name.c_str(), "1.0.0", port,
8039 s_GetMyIP());
8040 NCBITEST_CHECK_NE_MT_SAFE(find_result, -1);
8041 BOOST_CHECK_NO_THROW(
8042 s_DeannounceCPP(node_name, "1.0.0", s_GetMyIP(), port));
8043 /* Check that server was removed from storage */
8044 find_result = s_FindAnnouncedServer(node_name.c_str(), "1.0.0", port,
8045 s_GetMyIP());
8046 NCBITEST_CHECK_EQUAL_MT_SAFE(find_result, 0);
8047 /*
8048 * III. Check with 0.0.0.0
8049 */
8050 WRITE_LOG("Part III. Check with IP");
8051 BOOST_CHECK_NO_THROW(s_AnnounceCPPSafe(node_name, "1.0.0", "", port,
8052 "http://0.0.0.0:8080/health"););
8053 /* Check that server is in storage */
8054 find_result = s_FindAnnouncedServer(node_name.c_str(), "1.0.0", port,
8055 "0.0.0.0");
8056 NCBITEST_CHECK_NE_MT_SAFE(find_result, 0);
8057 BOOST_CHECK_NO_THROW(
8058 s_DeannounceCPP(node_name, "1.0.0", "", port));
8059 /* Check that server was removed from storage */
8060 find_result = s_FindAnnouncedServer(node_name.c_str(), "1.0.0", port,
8061 "0.0.0.0");
8062 NCBITEST_CHECK_EQUAL_MT_SAFE(find_result, 0);
8063 }
8064
8065
8066 /* 3. Could not connect to provided LBOS : fail and return 0 */
8067 /* Test is NOT thread-safe. */
NoLBOS__Return0()8068 void NoLBOS__Return0()
8069 {
8070 WRITE_LOG("Could not connect to provided LBOS");
8071 WRITE_LOG("Expected exception with error code \"" <<
8072 "eLbosNotFound" <<
8073 "\", status code \"" << 450 <<
8074 "\", message \"" << "450\\n" << "\".");
8075 ExceptionComparator<CLBOSException::eLbosNotFound, 450>
8076 comparator("450\n");
8077 CLBOSStatus lbos_status(true, true);
8078 string node_name = s_GenerateNodeName();
8079 unsigned short port = kDefaultPort;
8080 CMockFunction<FLBOS_ConnReadMethod*> mock(
8081 g_LBOS_UnitTesting_GetLBOSFuncs()->Read,
8082 s_FakeReadEmpty);
8083 BOOST_CHECK_EXCEPTION(
8084 s_DeannounceCPP(node_name, "1.0.0", "", port),
8085 CLBOSException, comparator);
8086 }
8087
8088
8089 /* 4. Successfully connected to LBOS, but deannounce returned error:
8090 * return 0 */
8091 /* Test is thread-safe. */
LBOSExistsDeannounceError__Return0()8092 void LBOSExistsDeannounceError__Return0()
8093 {
8094 WRITE_LOG("Could not connect to provided LBOS");
8095 WRITE_LOG("Expected exception with error code \"" <<
8096 "eBadRequest" <<
8097 "\", status code \"" << 400 <<
8098 "\", message \"" << "400 Bad Request\\n" << "\".");
8099 ExceptionComparator<CLBOSException::eBadRequest, 400>
8100 comparator("400 Bad Request\n");
8101 CLBOSStatus lbos_status(true, true);
8102 /* Currently LBOS does not return any errors */
8103 /* Here we can try to deannounce something non-existent */
8104 unsigned short port = kDefaultPort;
8105 BOOST_CHECK_EXCEPTION(
8106 s_DeannounceCPP("no such service", "no such version", "127.0.0.1",
8107 port),
8108 CLBOSException, comparator);
8109 }
8110
8111
8112 /* 5. Real-life test: after de-announcement server should be invisible
8113 * to resolve */
8114 /* Test is thread-safe. */
RealLife__InvisibleAfterDeannounce()8115 void RealLife__InvisibleAfterDeannounce()
8116 {
8117 WRITE_LOG("Real-life test : after de-announcement server should "
8118 "be invisible to resolve");
8119 CLBOSStatus lbos_status(true, true);
8120 /* It is best to take test Deannounced__Return1() and just check number
8121 * of servers after the test */
8122 string node_name = s_GenerateNodeName();
8123 unsigned short port = kDefaultPort;
8124 /* Prepare for test. We need to be sure that there is no previously
8125 * registered non-deleted service. We count server with chosen port
8126 * and check if there is no server already announced */
8127 int count_before;
8128 SELECT_PORT(count_before, node_name, port);
8129 Deannounced__Return1(port);
8130 int count_after = s_CountServersWithExpectation(node_name, port, 0,
8131 __LINE__,
8132 kDiscoveryDelaySec);
8133 NCBITEST_CHECK_EQUAL_MT_SAFE(count_after - count_before, 0);
8134 }
8135
8136
8137 /* 7. Deannounce without IP specified - deannounce from local host */
8138 /* Test is NOT thread-safe. */
NoHostProvided__LocalAddress()8139 void NoHostProvided__LocalAddress()
8140 {
8141 WRITE_LOG("Deannounce without IP specified - deannounce from local host");
8142 CLBOSStatus lbos_status(true, true);
8143 string node_name = s_GenerateNodeName();
8144 unsigned short port = kDefaultPort;
8145 /* Prepare for test. We need to be sure that there is no previously
8146 * registered non-deleted service. We count server with chosen port
8147 * and check if there is no server already announced */
8148 int count_before;
8149 SELECT_PORT(count_before, node_name, port);
8150 try {
8151 // We get random answers of LBOS in this test, so try-catch
8152 // Service always get announced, though
8153 s_AnnounceCPP(node_name, "1.0.0", "",
8154 port, "http://" ANNOUNCEMENT_HOST_0000 ":" + s_PortStr(PORT_N) + "/health");
8155 }
8156 catch (...) {
8157 }
8158 stringstream healthcheck;
8159 healthcheck << ":" + s_PortStr(PORT_N) + "/health" << "?port=" << port <<
8160 "&host=" << "" << "&version=" << "1.0.0";
8161 bool is_announced = s_CheckIfAnnounced(node_name, "1.0.0", port,
8162 healthcheck.str().c_str(),
8163 true);
8164 NCBITEST_CHECK_EQUAL_MT_SAFE(is_announced, true);
8165 BOOST_CHECK_NO_THROW(
8166 s_DeannounceCPP(node_name, "1.0.0", "", port));
8167 is_announced = s_CheckIfAnnounced(node_name, "1.0.0", port,
8168 ":" + s_PortStr(PORT_N) + "/health",
8169 false);
8170 NCBITEST_CHECK_EQUAL_MT_SAFE(is_announced, false);
8171 }
8172
8173 /* 8. LBOS is OFF - return eLBOS_Disabled */
8174 /* Test is NOT thread-safe. */
LBOSOff__ThrowKLBOSOff()8175 void LBOSOff__ThrowKLBOSOff()
8176 {
8177 WRITE_LOG("Deannonce when LBOS mapper is OFF");
8178 WRITE_LOG("Expected exception with error code \"" <<
8179 "eDisabled" <<
8180 "\", status code \"" << 550 <<
8181 "\", message \"" << "550\\n" << "\".");
8182 ExceptionComparator<CLBOSException::eDisabled, 550>
8183 comparator("550\n");
8184 CLBOSStatus lbos_status(true, false);
8185 BOOST_CHECK_EXCEPTION(
8186 s_DeannounceCPP("lbostest", "1.0.0", "", 8080),
8187 CLBOSException, comparator);
8188 }
8189
8190
8191 /* 9. Trying to deannounce non-existent service - throw eLbosNotFound */
8192 /* Test is thread-safe. */
NotExists__ThrowE_NotFound()8193 void NotExists__ThrowE_NotFound()
8194 {
8195 WRITE_LOG("Deannonce non-existent service");
8196 WRITE_LOG("Expected exception with error code \"" <<
8197 "eLbosNotFound" <<
8198 "\", status code \"" << 404 <<
8199 "\", message \"" << "404 Not Found\\n" << "\".");
8200 ExceptionComparator<CLBOSException::eNotFound, 404>
8201 comparator("404 Not Found\n");
8202 CLBOSStatus lbos_status(true, true);
8203 BOOST_CHECK_EXCEPTION(
8204 s_DeannounceCPP("notexists", "1.0.0", "", 8080),
8205 CLBOSException, comparator);
8206 }
8207
8208 }
8209 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
8210 namespace DeannouncementAll_CXX
8211 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
8212 {
8213 /* 1. If function was called and no servers were announced after call, no
8214 announced servers should be found in LBOS
8215 No Multithread! */
AllDeannounced__NoSavedLeft()8216 void AllDeannounced__NoSavedLeft()
8217 {
8218 WRITE_LOG("DeannonceAll - should deannounce everything "
8219 "that was announced");
8220 CLBOSStatus lbos_status(true, true);
8221 /* First, announce some random servers */
8222 vector<unsigned short> ports, counts_before, counts_after;
8223 unsigned int i = 0;
8224 string node_name = s_GenerateNodeName();
8225 unsigned short port = kDefaultPort;
8226 WRITE_LOG("Part I. Announcing");
8227 for (i = 0; i < 10; i++) {
8228 int count_before;
8229 SELECT_PORT(count_before, node_name, port);
8230 ports.push_back(port);
8231 counts_before.push_back(count_before);
8232 BOOST_CHECK_NO_THROW(
8233 s_AnnounceCPPSafe(node_name, "1.0.0", "", ports[i],
8234 "http://" ANNOUNCEMENT_HOST_0000 ":" +
8235 s_PortStr(PORT_N) + "/health"));
8236 }
8237 WRITE_LOG("Part II. DeannounceAll");
8238 BOOST_CHECK_NO_THROW(LBOS::DeannounceAll());
8239
8240 WRITE_LOG("Part III. Checking discovery - should find nothing");
8241 for (i = 0; i < ports.size(); i++) {
8242 counts_after.push_back(s_CountServers(s_GenerateNodeName(), ports[i]));
8243 NCBITEST_CHECK_EQUAL_MT_SAFE(counts_before[i], counts_after[i]);
8244 }
8245 }
8246 }
8247
8248
8249 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
8250 namespace Initialization
8251 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
8252 {
8253 /** Multithread simultaneous SERV_LBOS_Open() when LBOS is not yet
8254 * initialized should not crash */
MultithreadInitialization__ShouldNotCrash()8255 void MultithreadInitialization__ShouldNotCrash()
8256 {
8257 #ifdef LBOS_TEST_MT
8258 CLBOSStatus lbos_status(false, false);
8259 GeneralLBOS::LbosExist__ShouldWork();
8260 #endif
8261 }
8262
8263
8264 /** At initialization if no LBOS found, mapper must be turned OFF */
InitializationFail__TurnOff()8265 void InitializationFail__TurnOff()
8266 {
8267 CLBOSStatus lbos_status(false, true);
8268 string service = "/lbos";
8269 CCounterResetter resetter(s_CallCounter);
8270
8271 CMockFunction<FLBOS_FillCandidatesMethod*> mock(
8272 g_LBOS_UnitTesting_GetLBOSFuncs()->FillCandidates,
8273 s_FakeFillCandidates<0>);
8274
8275 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
8276 SERV_LOCALHOST, 0, 0.0,
8277 0, 0, 0, 0, 0, 0));
8278 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter == NULL,
8279 "LBOS found when it should not be");
8280 NCBITEST_CHECK_MESSAGE_MT_SAFE(*(g_LBOS_UnitTesting_PowerStatus()) == 0,
8281 "LBOS has not been shut down as it should be");
8282 }
8283
8284
8285 /** At initialization if LBOS found, mapper should be ON */
InitializationSuccess__StayOn()8286 void InitializationSuccess__StayOn()
8287 {
8288 CLBOSStatus lbos_status(false, false);
8289 string service = "/lbos";
8290 CCounterResetter resetter(s_CallCounter);
8291
8292 CMockFunction<FLBOS_FillCandidatesMethod*> mock(
8293 g_LBOS_UnitTesting_GetLBOSFuncs()->FillCandidates,
8294 s_FakeFillCandidates<1>);
8295
8296 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
8297 SERV_LOCALHOST, 0, 0.0,
8298 0, 0, 0, 0, 0, 0));
8299 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter != NULL,
8300 "LBOS not found when it should be");
8301 NCBITEST_CHECK_MESSAGE_MT_SAFE(*(g_LBOS_UnitTesting_PowerStatus()) == 1,
8302 "LBOS is not turned ON as it should be");
8303
8304 }
8305
8306
8307 /** If LBOS has not yet been initialized, it should be initialized at
8308 * SERV_LBOS_Open() */
OpenNotInitialized__ShouldInitialize()8309 void OpenNotInitialized__ShouldInitialize()
8310 {
8311 CMockFunction<FLBOS_InitializeMethod*> mock (
8312 g_LBOS_UnitTesting_GetLBOSFuncs()->Initialize,
8313 s_FakeInitialize);
8314 CLBOSStatus lbos_status(false, false);
8315 string service = "/lbos";
8316 CCounterResetter resetter(s_CallCounter);
8317
8318 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
8319 SERV_LOCALHOST, 0, 0.0,
8320 0, 0, 0, 0, 0, 0, 0));
8321 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter == NULL,
8322 "Error: LBOS found when mapper is OFF");
8323 NCBITEST_CHECK_MESSAGE_MT_SAFE(s_CallCounter == 1,
8324 "Initialization was not called "
8325 "when it should be");
8326 }
8327
8328
8329 /** If LBOS turned OFF, it MUST return NULL on SERV_LBOS_Open() */
OpenWhenTurnedOff__ReturnNull()8330 void OpenWhenTurnedOff__ReturnNull()
8331 {
8332 CLBOSStatus lbos_status(true, false);
8333 string service = "/lbos";
8334 CCounterResetter resetter(s_CallCounter);
8335 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
8336 SERV_LOCALHOST, 0, 0.0,
8337 0, 0, 0, 0, 0, 0));
8338 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter == NULL,
8339 "SERV_LBOS_Open did not return NULL "
8340 "when it is disabled");
8341
8342 /* Cleanup */
8343 *(g_LBOS_UnitTesting_PowerStatus()) = 1;
8344 *(g_LBOS_UnitTesting_InitStatus()) = 0;
8345 }
8346
8347
8348 /** s_LBOS_InstancesList MUST not be NULL at beginning of
8349 * s_LBOS_Initialize() */
s_LBOS_Initialize__s_LBOS_InstancesListNotNULL()8350 void s_LBOS_Initialize__s_LBOS_InstancesListNotNULL()
8351 {
8352 CMockFunction<FLBOS_InitializeMethod*> mock (
8353 g_LBOS_UnitTesting_GetLBOSFuncs()->Initialize,
8354 s_FakeInitializeCheckInstances);
8355 CLBOSStatus lbos_status(false, true);
8356 string service = "/lbos";
8357 CCounterResetter resetter(s_CallCounter);
8358
8359 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
8360 SERV_LOCALHOST, 0, 0.0,
8361 0, 0, 0, 0, 0, 0));
8362 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter != NULL,
8363 "LBOS not found when it should be");
8364 NCBITEST_CHECK_MESSAGE_MT_SAFE(s_CallCounter == 1,
8365 "Fake initialization was not called when it should be");
8366 }
8367
8368
8369 /** s_LBOS_InstancesList MUST not be NULL at beginning of
8370 * s_LBOS_FillCandidates() */
s_LBOS_FillCandidates__s_LBOS_InstancesListNotNULL()8371 void s_LBOS_FillCandidates__s_LBOS_InstancesListNotNULL()
8372 {
8373 CMockFunction<FLBOS_FillCandidatesMethod*> mock (
8374 g_LBOS_UnitTesting_GetLBOSFuncs()->FillCandidates,
8375 s_FakeFillCandidatesCheckInstances);
8376 CLBOSStatus lbos_status(false, true);
8377 string service = "/lbos";
8378 CCounterResetter resetter(s_CallCounter);
8379
8380 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
8381 SERV_LOCALHOST, 0, 0.0,
8382 0, 0, 0, 0, 0, 0));
8383
8384 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter != NULL,
8385 "LBOS not found when it should be");
8386 NCBITEST_CHECK_MESSAGE_MT_SAFE(s_CallCounter == 2,
8387 "Fill candidates was not called when "
8388 "it should be");
8389 }
8390
8391
8392
8393 } /* namespace Initialization */
8394
8395 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
8396 namespace Configure
8397 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
8398 {
8399 /* 1. Set version then check version - should show the version that was
8400 * just set.
8401 * Test is not for multi-threading */
SetThenCheck__ShowsSetVersion()8402 void SetThenCheck__ShowsSetVersion()
8403 {
8404 CLBOSStatus lbos_status(true, true);
8405 string node_name = s_GetUnknownService();
8406
8407 /* Set version */
8408 LBOSPrivate::SetServiceVersion(node_name, "1.0.0");
8409
8410 /* Check version */
8411 string conf_data = LBOSPrivate::GetServiceVersion(node_name);
8412 NCBITEST_CHECK_EQUAL_MT_SAFE(conf_data, "1.0.0");
8413
8414 /* Cleanup */
8415 LBOSPrivate::DeleteServiceVersion(node_name);
8416 }
8417
8418 /* 2. Check version, then set different version, then check version -
8419 * should show new version.
8420 * Test is not for multi-threading */
CheckSetNewCheck__ChangesVersion()8421 void CheckSetNewCheck__ChangesVersion()
8422 {
8423 CLBOSStatus lbos_status(true, true);
8424 string node_name = s_GetUnknownService();
8425
8426 /* Check version and save it */
8427 string conf_data = LBOSPrivate::GetServiceVersion(node_name);
8428 string prev_version = conf_data;
8429
8430 /* Set different version */
8431 conf_data = LBOSPrivate::SetServiceVersion(node_name, prev_version + ".0");
8432 NCBITEST_CHECK_EQUAL_MT_SAFE(conf_data, prev_version);
8433
8434 /* Check version */
8435 conf_data = LBOSPrivate::GetServiceVersion(node_name);
8436 NCBITEST_CHECK_EQUAL_MT_SAFE(conf_data, prev_version + ".0");
8437
8438 /* Cleanup */
8439 LBOSPrivate::DeleteServiceVersion(node_name);
8440 }
8441
8442 /* 3. Set version, check that it was set, then delete version - check
8443 * that no version exists.
8444 * Test is not for multi-threading */
DeleteThenCheck__SetExistsFalse()8445 void DeleteThenCheck__SetExistsFalse()
8446 {
8447 bool exists;
8448 CLBOSStatus lbos_status(true, true);
8449 string node_name = s_GetUnknownService();
8450 ExceptionComparator<CLBOSException::eLbosNotFound, 404> comp("404\n");
8451
8452 /* Set version */
8453 LBOSPrivate::SetServiceVersion(node_name, "1.0.0", &exists);
8454
8455 /* Delete version */
8456 string conf_data = LBOSPrivate::DeleteServiceVersion(node_name);
8457 NCBITEST_CHECK_EQUAL_MT_SAFE(conf_data, "1.0.0");
8458
8459 /* Check version */
8460 LBOSPrivate::GetServiceVersion(node_name, &exists);
8461 NCBITEST_CHECK_EQUAL_MT_SAFE(exists, false);
8462
8463 /* Cleanup */
8464 LBOSPrivate::DeleteServiceVersion(node_name);
8465 }
8466
8467 /* 4. Announce two servers with different version. First, set one version
8468 * and discover server with that version. Then, set the second version
8469 * and discover server with that version.
8470 * Test is not for multi-threading */
AnnounceThenChangeVersion__DiscoverAnotherServer()8471 void AnnounceThenChangeVersion__DiscoverAnotherServer()
8472 {
8473 CLBOSStatus lbos_status(true, true);
8474 string node_name = s_GetUnknownService();
8475 unsigned short port1, port2;
8476 string health = string("http://") + ANNOUNCEMENT_HOST + ":" +
8477 s_PortStr(PORT_N) + "/health";
8478 int count_before;
8479 SELECT_PORT(count_before, node_name, port1);
8480 s_AnnounceCPPSafe(node_name, "v1", "", port1, health.c_str());
8481
8482 SELECT_PORT(count_before, node_name, port2);
8483 s_AnnounceCPPSafe(node_name, "v2", "", port2, health.c_str());
8484
8485 /* Set first version */
8486 LBOSPrivate::SetServiceVersion(node_name, "v1");
8487 unsigned int servers_found =
8488 s_CountServersWithExpectation(node_name, port1, 1, __LINE__,
8489 kDiscoveryDelaySec, "");
8490 NCBITEST_CHECK_EQUAL_MT_SAFE(servers_found, 1U);
8491 servers_found =
8492 s_CountServersWithExpectation(node_name, port2, 0, __LINE__,
8493 kDiscoveryDelaySec, "");
8494 NCBITEST_CHECK_EQUAL_MT_SAFE(servers_found, 0U);
8495
8496 /* Set second version and discover */
8497 LBOSPrivate::SetServiceVersion(node_name, "v2");
8498 servers_found =
8499 s_CountServersWithExpectation(node_name, port1, 0, __LINE__,
8500 kDiscoveryDelaySec, "");
8501 NCBITEST_CHECK_EQUAL_MT_SAFE(servers_found, 0U);
8502 servers_found =
8503 s_CountServersWithExpectation(node_name, port2, 1, __LINE__,
8504 kDiscoveryDelaySec, "");
8505 NCBITEST_CHECK_EQUAL_MT_SAFE(servers_found, 1U);
8506
8507 /* Cleanup */
8508 s_DeannounceCPP(node_name, "v1", "", port1);
8509 s_DeannounceCPP(node_name, "v2", "", port2);
8510 LBOSPrivate::DeleteServiceVersion(node_name);
8511
8512 }
8513
8514 /* 5. Announce one server. Discover it. Then delete version. Try to
8515 * discover it again, should not find.
8516 * Test is not for multi-threading */
AnnounceThenDeleteVersion__DiscoverFindsNothing()8517 void AnnounceThenDeleteVersion__DiscoverFindsNothing()
8518 {
8519 CLBOSStatus lbos_status(true, true);
8520 string node_name = s_GetUnknownService();
8521 unsigned short port;
8522
8523 /* Set version */
8524 LBOSPrivate::SetServiceVersion(node_name, "1.0.0");
8525
8526 /* Announce and discover */
8527 string health = string("http://") + ANNOUNCEMENT_HOST + ":" +
8528 s_PortStr(PORT_N) + "/health";
8529 int count_before;
8530 SELECT_PORT(count_before, node_name, port);
8531 s_AnnounceCPPSafe(node_name, "1.0.0", "", port, health.c_str());
8532 unsigned int servers_found =
8533 s_CountServersWithExpectation(node_name, port, 1, __LINE__,
8534 kDiscoveryDelaySec, "");
8535 NCBITEST_CHECK_EQUAL_MT_SAFE(servers_found, 1U);
8536
8537 /* Delete version and not discover */
8538 LBOSPrivate::DeleteServiceVersion(node_name);
8539 servers_found =
8540 s_CountServersWithExpectation(node_name, port, 0, __LINE__,
8541 kDiscoveryDelaySec, "");
8542 NCBITEST_CHECK_EQUAL_MT_SAFE(servers_found, 0U);
8543
8544 /* Cleanup */
8545 LBOSPrivate::DeleteServiceVersion(node_name);
8546 s_DeannounceCPP(node_name, "1.0.0", "", port);
8547 }
8548
8549 /* 6. Set with no service - invalid args */
SetNoService__InvalidArgs()8550 void SetNoService__InvalidArgs()
8551 {
8552 CLBOSStatus lbos_status(true, true);
8553 ExceptionComparator<CLBOSException::eInvalidArgs, 452>
8554 comp("452\n");
8555
8556 /* Set version */
8557 BOOST_CHECK_EXCEPTION(LBOSPrivate::SetServiceVersion("", "1.0.0"),
8558 CLBOSException,
8559 comp);
8560 }
8561
8562 /* 7. Get with no service - invalid args */
GetNoService__InvalidArgs()8563 void GetNoService__InvalidArgs()
8564 {
8565 CLBOSStatus lbos_status(true, true);
8566 ExceptionComparator<CLBOSException::eInvalidArgs, 452>
8567 comp("452\n");
8568
8569 /* Set version */
8570 BOOST_CHECK_EXCEPTION(LBOSPrivate::GetServiceVersion(""),
8571 CLBOSException,
8572 comp);
8573 }
8574
8575 /* 8. Delete with no service - invalid args */
DeleteNoService__InvalidArgs()8576 void DeleteNoService__InvalidArgs()
8577 {
8578 CLBOSStatus lbos_status(true, true);
8579 ExceptionComparator<CLBOSException::eInvalidArgs, 452>
8580 comp("452\n");
8581
8582 /* Set version */
8583 BOOST_CHECK_EXCEPTION(LBOSPrivate::DeleteServiceVersion(""),
8584 CLBOSException,
8585 comp);
8586 }
8587
8588 /* 9. Set with empty version - OK */
SetEmptyVersion__OK()8589 void SetEmptyVersion__OK()
8590 {
8591 CLBOSStatus lbos_status(true, true);
8592 string node_name = s_GetUnknownService();
8593 ExceptionComparator<CLBOSException::eInvalidArgs, 452> comp("452\n");
8594
8595 /* Set version */
8596 BOOST_CHECK_EXCEPTION(LBOSPrivate::SetServiceVersion(node_name, ""),
8597 CLBOSException, comp);
8598
8599 /* Check empty version */
8600 string cur_version = LBOSPrivate::GetServiceVersion(node_name);
8601 NCBITEST_CHECK_EQUAL_MT_SAFE(cur_version, "");
8602
8603 /* Cleanup */
8604 LBOSPrivate::DeleteServiceVersion(node_name);
8605 }
8606
8607 /* 10. Set with empty version no service - invalid args */
SetNoServiceEmptyVersion__InvalidArgs()8608 void SetNoServiceEmptyVersion__InvalidArgs()
8609 {
8610 CLBOSStatus lbos_status(true, true);
8611 ExceptionComparator<CLBOSException::eInvalidArgs, 452> comp("452\n");
8612
8613 /* Set version */
8614 BOOST_CHECK_EXCEPTION(LBOSPrivate::SetServiceVersion("", ""),
8615 CLBOSException,
8616 comp);
8617 }
8618
8619 /* 11. Get, set, delete with service that does not exist, providing
8620 * "exists" parameter - this parameter should be false and version
8621 * should be empty */
ServiceNotExistsAndBoolProvided__EqualsFalse()8622 void ServiceNotExistsAndBoolProvided__EqualsFalse()
8623 {
8624 CLBOSStatus lbos_status(true, true);
8625 string node_name = s_GetUnknownService();
8626 bool exists = true;
8627 string conf_version = "1";
8628
8629 /* Get version */
8630 conf_version = LBOSPrivate::GetServiceVersion(node_name, &exists);
8631 NCBITEST_CHECK_EQUAL_MT_SAFE(exists, false);
8632 NCBITEST_CHECK_EQUAL_MT_SAFE(conf_version, "");
8633 conf_version = "1";
8634 exists = true;
8635
8636 /* Delete */
8637 conf_version = LBOSPrivate::DeleteServiceVersion(node_name, &exists);
8638 NCBITEST_CHECK_EQUAL_MT_SAFE(exists, false);
8639 NCBITEST_CHECK_EQUAL_MT_SAFE(conf_version, "");
8640 conf_version = "1";
8641 exists = true;
8642
8643 /* Set version */
8644 conf_version = LBOSPrivate::SetServiceVersion(node_name, "1.0.0", &exists);
8645 NCBITEST_CHECK_EQUAL_MT_SAFE(exists, false);
8646 NCBITEST_CHECK_EQUAL_MT_SAFE(conf_version, "");
8647 conf_version = "1";
8648 exists = true;
8649
8650 /* Cleanup */
8651 LBOSPrivate::DeleteServiceVersion(node_name);
8652 }
8653
8654 /* 12. Get, set, delete with service that does exist, providing
8655 * "exists" parameter - this parameter should be true and version
8656 * should be filled */
ServiceExistsAndBoolProvided__EqualsTrue()8657 void ServiceExistsAndBoolProvided__EqualsTrue()
8658 {
8659 CLBOSStatus lbos_status(true, true);
8660 string node_name = s_GetUnknownService();
8661 bool exists = false;
8662 string conf_version = "1";
8663 LBOSPrivate::SetServiceVersion(node_name, "1.0.0", &exists);
8664
8665 /* Get version */
8666 conf_version = LBOSPrivate::GetServiceVersion(node_name, &exists);
8667 NCBITEST_CHECK_EQUAL_MT_SAFE(exists, true);
8668 NCBITEST_CHECK_EQUAL_MT_SAFE(conf_version, "1.0.0");
8669 conf_version = "1";
8670 exists = false;
8671
8672 /* Set version */
8673 conf_version = LBOSPrivate::SetServiceVersion(node_name, "1.0.0", &exists);
8674 NCBITEST_CHECK_EQUAL_MT_SAFE(exists, true);
8675 NCBITEST_CHECK_EQUAL_MT_SAFE(conf_version, "1.0.0");
8676 conf_version = "1";
8677 exists = false;
8678
8679 /* Delete (and also a cleanup) */
8680 conf_version = LBOSPrivate::DeleteServiceVersion(node_name, &exists);
8681 NCBITEST_CHECK_EQUAL_MT_SAFE(exists, true);
8682 NCBITEST_CHECK_EQUAL_MT_SAFE(conf_version, "1.0.0");
8683 conf_version = "1";
8684 exists = false;
8685 }
8686
8687 /* 13. Get, set, delete with service that does not exist, not providing
8688 * "exists" parameter - version should be empty and no crash should
8689 * happen*/
ServiceNotExistsAndBoolNotProvided__NoCrash()8690 void ServiceNotExistsAndBoolNotProvided__NoCrash()
8691 {
8692 CLBOSStatus lbos_status(true, true);
8693 string node_name = s_GetUnknownService();
8694 string conf_version = "1";
8695
8696 /* Get version */
8697 conf_version = LBOSPrivate::GetServiceVersion(node_name);
8698 NCBITEST_CHECK_EQUAL_MT_SAFE(conf_version, "");
8699 conf_version = "1";
8700
8701 /* Delete */
8702 conf_version = LBOSPrivate::DeleteServiceVersion(node_name);
8703 NCBITEST_CHECK_EQUAL_MT_SAFE(conf_version, "");
8704 conf_version = "1";
8705
8706 /* Set version */
8707 conf_version = LBOSPrivate::SetServiceVersion(node_name, "1.0.0");
8708 NCBITEST_CHECK_EQUAL_MT_SAFE(conf_version, "");
8709 conf_version = "1";
8710
8711 /* Cleanup */
8712 LBOSPrivate::DeleteServiceVersion(node_name);
8713 }
8714
8715 /* 14. Get, set, delete with service that does exist, not providing
8716 * "exists" parameter - this parameter should be true and version
8717 * should be filled */
ServiceExistsAndBoolNotProvided__NoCrash()8718 void ServiceExistsAndBoolNotProvided__NoCrash()
8719 {
8720 CLBOSStatus lbos_status(true, true);
8721 string node_name = s_GetUnknownService();
8722 string conf_version = "1";
8723 LBOSPrivate::SetServiceVersion(node_name, "1.0.0");
8724
8725 /* Get version */
8726 conf_version = LBOSPrivate::GetServiceVersion(node_name);
8727 NCBITEST_CHECK_EQUAL_MT_SAFE(conf_version, "1.0.0");
8728 conf_version = "1";
8729
8730 /* Set version */
8731 conf_version = LBOSPrivate::SetServiceVersion(node_name, "1.0.0");
8732 NCBITEST_CHECK_EQUAL_MT_SAFE(conf_version, "1.0.0");
8733 conf_version = "1";
8734
8735 /* Delete (and also a cleanup) */
8736 conf_version = LBOSPrivate::DeleteServiceVersion(node_name);
8737 NCBITEST_CHECK_EQUAL_MT_SAFE(conf_version, "1.0.0");
8738 conf_version = "1";
8739 }
8740 }
8741
8742 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
8743 namespace Stability
8744 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
8745 {
8746 void GetNext_Reset__ShouldNotCrash();
8747 void FullCycle__ShouldNotCrash();
8748
8749
GetNext_Reset__ShouldNotCrash()8750 void GetNext_Reset__ShouldNotCrash()
8751 {
8752 WRITE_LOG("Stability test 1: only reset() and get_next(), iterator is "
8753 "not closed");
8754 CLBOSStatus lbos_status(true, true);
8755 int secondsBeforeStop = 10; /* when to stop this test */
8756 struct ::timeval start; /**< we will measure time from start
8757 of test as main measure of when
8758 to finish */
8759 struct timeval stop;
8760 if (s_GetTimeOfDay(&start) != 0) {
8761 memset(&start, 0, sizeof(start));
8762 }
8763 string service = "/lbos";
8764 const SSERV_Info* info = NULL;
8765 int i = 0;
8766 CConnNetInfo net_info;
8767 double elapsed = 0.0;
8768
8769 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
8770 SERV_LOCALHOST, 0, 0.0,
8771 *net_info, 0, 0, 0, 0, 0));
8772 for (i = 0; elapsed < secondsBeforeStop; ++i) {
8773 do {
8774 info = SERV_GetNextInfoEx(*iter, NULL);
8775 } while (info != NULL);
8776 SERV_Reset(*iter);
8777 if (s_GetTimeOfDay(&stop) != 0)
8778 memset(&stop, 0, sizeof(stop));
8779 elapsed = s_TimeDiff(&stop, &start);
8780 }
8781 }
8782
FullCycle__ShouldNotCrash()8783 void FullCycle__ShouldNotCrash()
8784 {
8785 WRITE_LOG("Stability test 2: full cycle with close(), open() and "
8786 "get_next()");
8787 CLBOSStatus lbos_status(true, true);
8788 int secondsBeforeStop = 10; /* when to stop this test */
8789 double elapsed = 0.0;
8790 struct timeval start; /**< we will measure time from start of test as main
8791 measure of when to finish */
8792 struct timeval stop;
8793 if (s_GetTimeOfDay(&start) != 0) {
8794 memset(&start, 0, sizeof(start));
8795 }
8796 string service = "/lbos";
8797 const SSERV_Info* info = NULL;
8798 int i = 0;
8799 CConnNetInfo net_info;
8800 for (i = 0; elapsed < secondsBeforeStop; ++i) {
8801 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
8802 SERV_LOCALHOST, 0, 0.0,
8803 *net_info, 0, 0, 0, 0, 0));
8804 do {
8805 info = SERV_GetNextInfoEx(*iter, NULL);
8806 } while (info != NULL);
8807 if (s_GetTimeOfDay(&stop) != 0)
8808 memset(&stop, 0, sizeof(stop));
8809 elapsed = s_TimeDiff(&stop, &start);
8810 }
8811 }
8812 } /* namespace Stability */
8813
8814
8815 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
8816 namespace Performance
8817 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
8818 {
8819 void FullCycle__ShouldNotCrash();
8820
FullCycle__ShouldNotCrash()8821 void FullCycle__ShouldNotCrash()
8822 {
8823 WRITE_LOG("Performance test: full cycle with close(), open() and "
8824 "get_next()");
8825 CLBOSStatus lbos_status(true, true);
8826 int secondsBeforeStop = 10; /* when to stop this test */
8827 double total_elapsed = 0.0;
8828 double cycle_elapsed = 0.0; /**< we check performance
8829 every second */
8830 struct timeval start; /**< we will measure time from
8831 start of test as main
8832 measure of when to
8833 finish */
8834 struct timeval cycle_start; /**< to measure start of
8835 current cycle */
8836 struct timeval stop; /**< To check time at
8837 the end of each
8838 iterations */
8839 string service = "/lbos";
8840 const SSERV_Info* info;
8841 int total_iters = 0; /**< Total number of full
8842 iterations since start of
8843 test */
8844 int cycle_iters = 0; /**< Total number of full
8845 iterations since start
8846 of one second cycle */
8847 int total_hosts = 0; /**< Total number of found
8848 hosts since start of
8849 test */
8850 int cycle_hosts = 0; /**< number of full
8851 iterations since start of
8852 one second cycle */
8853 int max_iters_per_cycle = 0; /**< Maximum iterations
8854 per one second cycle */
8855 int min_iters_per_cycle = INT_MAX; /**< Minimum iterations
8856 per one second cycle */
8857 int max_hosts_per_cycle = 0; /**< Maximum hosts found
8858 per one second cycle */
8859 int min_hosts_per_cycle = INT_MAX; /**< Minimum hosts found
8860 per one second cycle */
8861 /*
8862 * Basic initialization
8863 */
8864
8865 CConnNetInfo net_info;
8866
8867 if (s_GetTimeOfDay(&start) != 0) { //Initialize time of test start
8868 memset(&start, 0, sizeof(start));
8869 }
8870 if (s_GetTimeOfDay(&cycle_start) != 0) { /*Initialize time of
8871 iteration start*/
8872 memset(&cycle_start, 0, sizeof(cycle_start));
8873 }
8874 /*
8875 * Start running iterations
8876 */
8877 for (total_iters = 0, cycle_iters = 0; total_elapsed < secondsBeforeStop;
8878 ++total_iters, ++cycle_iters) {
8879 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
8880 SERV_LOCALHOST, 0, 0.0,
8881 *net_info, 0, 0, 0, 0, 0));
8882 int hosts_found = 0;
8883 while ((info = SERV_GetNextInfoEx(*iter, NULL)) != NULL) {
8884 ++hosts_found;
8885 ++total_hosts;
8886 ++cycle_hosts;;
8887 }
8888 s_CallCounter = 0;
8889 if (s_GetTimeOfDay(&stop) != 0)
8890 memset(&stop, 0, sizeof(stop));
8891 total_elapsed = s_TimeDiff(&stop, &start);
8892 cycle_elapsed = s_TimeDiff(&stop, &cycle_start);
8893 if (cycle_elapsed > 1.0) { /* If our cycle is 1 second finished,
8894 get some analytics and restart */
8895 if (cycle_iters > max_iters_per_cycle) {
8896 max_iters_per_cycle = cycle_iters;
8897 }
8898 if (cycle_iters < min_iters_per_cycle) {
8899 min_iters_per_cycle = cycle_iters;
8900 }
8901 if (cycle_hosts > max_hosts_per_cycle) {
8902 max_hosts_per_cycle = cycle_hosts;
8903 }
8904 if (cycle_hosts < min_hosts_per_cycle) {
8905 min_hosts_per_cycle = cycle_hosts;
8906 }
8907 cycle_iters = 0;
8908 cycle_hosts = 0;
8909 if (s_GetTimeOfDay(&cycle_start) != 0)
8910 memset(&cycle_start, 0, sizeof(cycle_start));
8911 }
8912 }
8913 WRITE_LOG("Performance test:\n"
8914 "Iterations:\n"
8915 "\t Min: " << min_iters_per_cycle << " iters/sec\n"
8916 "\t Max: " << max_iters_per_cycle << " iters/sec\n"
8917 "\t Avg: " << static_cast<double>(total_iters)/total_elapsed <<
8918 " iters/sec\n"
8919 "Found hosts:\n"
8920 "\t Min: " << min_hosts_per_cycle << " hosts/sec\n"
8921 "\t Max: " << max_hosts_per_cycle << " hosts/sec\n"
8922 "\t Avg: " << static_cast<double>(total_hosts)/total_elapsed <<
8923 " hosts/sec\n");
8924 }
8925 } /* namespace Performance */
8926
8927
8928 // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
8929 namespace MultiThreading
8930 // \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
8931 {
s_Stability_GetNextReset_ShouldNotCrash()8932 static void s_Stability_GetNextReset_ShouldNotCrash( ) {
8933 Stability::GetNext_Reset__ShouldNotCrash();
8934 }
s_Stability_FullCycle_ShouldNotCrash()8935 static void s_Stability_FullCycle_ShouldNotCrash( ) {
8936 Stability::FullCycle__ShouldNotCrash();
8937 }
s_Performance_FullCycle_ShouldNotCrash()8938 static void s_Performance_FullCycle_ShouldNotCrash( ) {
8939 Performance::FullCycle__ShouldNotCrash();
8940 }
8941
8942 class CMainLoopThread : public CThread
8943 {
8944 public:
CMainLoopThread(void (* testFunc)(),int idx)8945 CMainLoopThread(void (*testFunc)(), int idx)
8946 : m_TestFunc(testFunc), m_ThreadIdx(idx)
8947 {
8948 }
~CMainLoopThread()8949 ~CMainLoopThread()
8950 {
8951 }
8952
8953 private:
Main(void)8954 void* Main(void) {
8955 s_Tls->SetValue(new int, TlsCleanup);
8956 *s_Tls->GetValue() = m_ThreadIdx;
8957 #ifdef NCBI_MONKEY
8958 CMonkey::Instance()->RegisterThread(m_ThreadIdx);
8959 #endif /* NCBI_MONKEY */
8960 m_TestFunc();
8961 return NULL;
8962 }
8963 void (*m_TestFunc)();
8964 int m_ThreadIdx;
8965 };
8966 CMainLoopThread* thread1;
8967 CMainLoopThread* thread2;
8968 CMainLoopThread* thread3;
8969
8970
TryMultiThread()8971 void TryMultiThread()
8972 {
8973 #define LIST_OF_FUNCS \
8974 X(2, ResetIterator::NoConditions__IterContainsZeroCandidates) \
8975 X(3, ResetIterator::MultipleReset__ShouldNotCrash) \
8976 X(4, ResetIterator::Multiple_AfterGetNextInfo__ShouldNotCrash) \
8977 X(5, CloseIterator::AfterOpen__ShouldWork) \
8978 X(6, CloseIterator::AfterReset__ShouldWork) \
8979 X(7, CloseIterator::AfterGetNextInfo__ShouldWork) \
8980 X(8, CloseIterator::FullCycle__ShouldWork) \
8981 X(9, ResolveViaLBOS::ServiceExists__ReturnHostIP) \
8982 X(10,ResolveViaLBOS::ServiceDoesNotExist__ReturnNULL) \
8983 X(11,ResolveViaLBOS::NoLBOS__ReturnNULL) \
8984 X(12,GetLBOSAddress::CustomHostNotProvided__SkipCustomHost) \
8985 X(13,GetNextInfo::WrongMapper__ReturnNull) \
8986 X(14,MultiThreading::s_Stability_GetNextReset_ShouldNotCrash) \
8987 X(15,MultiThreading::s_Stability_FullCycle_ShouldNotCrash) \
8988 X(16,MultiThreading::s_Performance_FullCycle_ShouldNotCrash) \
8989 X(18,IPCache::HostSeparate__TryFindReturnsHostkIP) \
8990 X(22,IPCache::ResolveEmpty__Error) \
8991 X(23,IPCache::Resolve0000__Return0000) \
8992 X(24,IPCache::DeannounceHost__TryFindDoesNotFind) \
8993 X(25,IPCache::ResolveTwice__SecondTimeNoOp) \
8994 X(26,IPCache::DeleteTwice__SecondTimeNoOp) \
8995 X(27,IPCache::TryFindTwice__SecondTimeNoOp)
8996
8997 #define X(num,name) CMainLoopThread* thread##num = new CMainLoopThread(name, num);
8998 LIST_OF_FUNCS
8999 #undef X
9000
9001 #define X(num,name) thread##num->Run();
9002 LIST_OF_FUNCS
9003 #undef X
9004
9005 #define X(num,name) thread##num->Join();
9006 LIST_OF_FUNCS
9007 #undef X
9008
9009 #undef LIST_OF_FUNCS
9010 }
9011 } /* namespace MultiThreading */
9012
9013 static
s_Msb(unsigned short x)9014 unsigned short s_Msb(unsigned short x)
9015 {
9016 unsigned int y;
9017 while ((y = x & (x - 1)) != 0)
9018 x = y;
9019 return x;
9020 }
9021
9022 static
s_OS(TNcbiOSType ostype)9023 const char* s_OS(TNcbiOSType ostype)
9024 {
9025 static char buf[40];
9026 TNcbiOSType msb = s_Msb(ostype);
9027 switch (msb) {
9028 case fOS_Unknown:
9029 return "unknown";
9030 case fOS_IRIX:
9031 return "IRIX";
9032 case fOS_Solaris:
9033 return "Solaris";
9034 case fOS_BSD:
9035 return ostype == fOS_Darwin ? "Darwin" : "BSD";
9036 case fOS_Windows:
9037 return (ostype & fOS_WindowsServer) == fOS_WindowsServer
9038 ? "WindowsServer" : "Windows";
9039 case fOS_Linux:
9040 return "Linux";
9041 default:
9042 break;
9043 }
9044 sprintf(buf, "(%hu)", ostype);
9045 return buf;
9046 }
9047
9048 static
s_Bits(TNcbiCapacity capacity)9049 const char* s_Bits(TNcbiCapacity capacity)
9050 {
9051 static char buf[40];
9052 switch (capacity) {
9053 case fCapacity_Unknown:
9054 return "unknown";
9055 case fCapacity_32:
9056 return "32";
9057 case fCapacity_64:
9058 return "64";
9059 case fCapacity_32_64:
9060 return "32+64";
9061 default:
9062 break;
9063 }
9064 sprintf(buf, "(%hu)", capacity);
9065 return buf;
9066 }
9067
9068
9069 #ifdef NCBI_OS_MSWIN
9070 static
s_GetTimeOfDay(struct timeval * tv)9071 int s_GetTimeOfDay(struct timeval* tv)
9072 {
9073 FILETIME systime;
9074 unsigned __int64 sysusec;
9075
9076 if (!tv)
9077 return -1;
9078
9079 GetSystemTimeAsFileTime(&systime);
9080
9081 sysusec = systime.dwHighDateTime;
9082 sysusec <<= 32;
9083 sysusec |= systime.dwLowDateTime;
9084 sysusec += 5;
9085 sysusec /= 10;
9086
9087 tv->tv_usec = (long)(sysusec % 1000000);
9088 tv->tv_sec = (long)(sysusec / 1000000 - 11644473600Ui64);
9089
9090 return 0;
9091 }
9092
9093 #else
9094
9095 # define s_GetTimeOfDay(tv) gettimeofday(tv, 0)
9096
9097 #endif
9098
9099 static
s_TimeDiff(const struct timeval * end,const struct timeval * beg)9100 double s_TimeDiff(const struct timeval* end,
9101 const struct timeval* beg)
9102 {
9103 if (end->tv_sec < beg->tv_sec)
9104 return 0.0;
9105 if (end->tv_usec < beg->tv_usec) {
9106 if (end->tv_sec == beg->tv_sec)
9107 return 0.0;
9108 return (end->tv_sec - beg->tv_sec - 1)
9109 + (end->tv_usec - beg->tv_usec + 1000000) / 1000000.0;
9110 }
9111 return (end->tv_sec - beg->tv_sec)
9112 + (end->tv_usec - beg->tv_usec) / 1000000.0;
9113 }
9114
9115 static
s_PrintInfo(HOST_INFO hinfo)9116 void s_PrintInfo(HOST_INFO hinfo)
9117 {
9118 const char kTimeFormat[] = "%m/%d/%y %H:%M:%S";
9119 time_t t;
9120 char buf[80];
9121 double array[5];
9122 SHINFO_Params params;
9123 const char* e = HINFO_Environment(hinfo);
9124 const char* a = HINFO_AffinityArgument(hinfo);
9125 const char* v = HINFO_AffinityArgvalue(hinfo);
9126 CORE_LOG(eLOG_Note, " Host info available:");
9127 CORE_LOGF(eLOG_Note, (" Number of CPUs: %d",
9128 HINFO_CpuCount(hinfo)));
9129 CORE_LOGF(eLOG_Note, (" Number of CPU units: %d @ %.0fMHz",
9130 HINFO_CpuUnits(hinfo),
9131 HINFO_CpuClock(hinfo)));
9132 CORE_LOGF(eLOG_Note, (" Number of tasks: %d",
9133 HINFO_TaskCount(hinfo)));
9134 if (HINFO_MachineParams(hinfo, ¶ms)) {
9135 CORE_LOGF(eLOG_Note, (" Arch: %d",
9136 params.arch));
9137 CORE_LOGF(eLOG_Note, (" OSType: %s",
9138 s_OS(params.ostype)));
9139 t = (time_t) params.bootup;
9140 strftime(buf, sizeof(buf), kTimeFormat, localtime(&t));
9141 CORE_LOGF(eLOG_Note, (" Kernel: %hu.%hu.%hu @ %s",
9142 params.kernel.major,
9143 params.kernel.minor,
9144 params.kernel.patch, buf));
9145 CORE_LOGF(eLOG_Note, (" Bits: %s",
9146 s_Bits(params.bits)));
9147 CORE_LOGF(eLOG_Note, (" Page size: %lu",
9148 (unsigned long) params.pgsize));
9149 t = (time_t) params.startup;
9150 strftime(buf, sizeof(buf), kTimeFormat, localtime(&t));
9151 CORE_LOGF(eLOG_Note, (" LBSMD: %hu.%hu.%hu @ %s",
9152 params.daemon.major,
9153 params.daemon.minor,
9154 params.daemon.patch, buf));
9155 } else
9156 CORE_LOG (eLOG_Note, " Machine params: unavailable");
9157 if (HINFO_Memusage(hinfo, array)) {
9158 CORE_LOGF(eLOG_Note, (" Total RAM: %.2fMB", array[0]));
9159 CORE_LOGF(eLOG_Note, (" Cache RAM: %.2fMB", array[1]));
9160 CORE_LOGF(eLOG_Note, (" Free RAM: %.2fMB", array[2]));
9161 CORE_LOGF(eLOG_Note, (" Total Swap: %.2fMB", array[3]));
9162 CORE_LOGF(eLOG_Note, (" Free Swap: %.2fMB", array[4]));
9163 } else
9164 CORE_LOG (eLOG_Note, " Memory usage: unavailable");
9165 if (HINFO_LoadAverage(hinfo, array)) {
9166 CORE_LOGF(eLOG_Note, (" Load averages: %f, %f (BLAST)",
9167 array[0], array[1]));
9168 } else
9169 CORE_LOG (eLOG_Note, " Load averages: unavailable");
9170 if (a) {
9171 assert(*a);
9172 CORE_LOGF(eLOG_Note, (" Affinity argument: %s", a));
9173 }
9174 if (a && v)
9175 CORE_LOGF(eLOG_Note, (" Affinity value: %s%s%s",
9176 *v ? "" : "\"", v, *v ? "" : "\""));
9177 CORE_LOGF(eLOG_Note, (" Host environment: %s%s%s",
9178 e? "\"": "", e? e: "NULL", e? "\"": ""));
9179 free(hinfo);
9180 }
9181
9182
9183 static
s_TestFindMethod(ELBOSFindMethod find_method)9184 void s_TestFindMethod(ELBOSFindMethod find_method)
9185 {
9186 string service = "/lbos";
9187
9188 const SSERV_Info* info = NULL;
9189 struct timeval start;
9190 int n_found = 0;
9191 CCObjHolder<char> lbos_address(g_LBOS_GetLBOSAddress());
9192 string lbos_addr(lbos_address.Get());
9193 CConnNetInfo net_info;
9194
9195 if (s_GetTimeOfDay(&start) != 0) {
9196 memset(&start, 0, sizeof(start));
9197 }
9198 CServIter iter(s_SERVOpenP_Safe(service.c_str(), fSERV_All,
9199 SERV_LOCALHOST, 0, 0.0,
9200 *net_info, 0, 0, 0, 0, 0));
9201 if (*iter == NULL) {
9202 NCBITEST_CHECK_MESSAGE_MT_SAFE(*iter != NULL,
9203 "LBOS not found when it should be");
9204 return;
9205 }
9206 /*
9207 * We know that iter is LBOS's. It must have clear info by implementation
9208 * before GetNextInfo is called, so we can set source of LBOS address now
9209 */
9210 static_cast<SLBOS_Data*>(iter->data)->lbos_addr =
9211 lbos_addr.c_str();
9212 /*ConnNetInfo_Destroy(*net_info);*/
9213 if (*iter) {
9214 g_LBOS_UnitTesting_SetLBOSFindMethod(*iter, find_method);
9215 HOST_INFO hinfo;
9216 while ((info = SERV_GetNextInfoEx(*iter, &hinfo)) != 0) {
9217 struct timeval stop;
9218 double elapsed;
9219 char* info_str;
9220 ++n_found;
9221 if (s_GetTimeOfDay(&stop) != 0)
9222 memset(&stop, 0, sizeof(stop));
9223 elapsed = s_TimeDiff(&stop, &start);
9224 info_str = SERV_WriteInfo(info);
9225 CORE_LOGF(eLOG_Note, ("Server #%-2d (%.6fs) `%s' = %s",
9226 ++n_found, elapsed, SERV_CurrentName(*iter),
9227 info_str ? info_str : "?"));
9228 if (hinfo) {
9229 s_PrintInfo(hinfo);
9230 }
9231 if (info_str)
9232 free(info_str);
9233 if (s_GetTimeOfDay(&start) != 0)
9234 memcpy(&start, &stop, sizeof(start));
9235 }
9236 CORE_LOGF(eLOG_Trace, ("Resetting the %s service mapper",
9237 SERV_MapperName(*iter)));
9238 SERV_Reset(*iter);
9239 CORE_LOG(eLOG_Trace, "Service mapper has been reset");
9240 NCBITEST_CHECK_MESSAGE_MT_SAFE (n_found && (info = SERV_GetNextInfo(*iter)),
9241 "Service not found after reset");
9242 }
9243 }
9244
9245
9246 /** Result of parsing of /service.
9247 * "is_enabled" tells if only enabled servers must be returned */
s_GetAnnouncedServers(bool is_enabled,vector<string> to_find)9248 static vector<SServer> s_GetAnnouncedServers(bool is_enabled,
9249 vector<string> to_find)
9250 {
9251 vector<SServer> nodes;
9252 CConnNetInfo net_info;
9253 size_t start = 0, end = 0;
9254 CCObjHolder<char> lbos_address(g_LBOS_GetLBOSAddress());
9255 string lbos_addr(lbos_address.Get());
9256 /*
9257 * Deannounce all lbostest servers (they are left if previous
9258 * launch of test crashed)
9259 */
9260 CCObjHolder<char> lbos_output_orig(g_LBOS_UnitTesting_GetLBOSFuncs()->
9261 UrlReadAll(*net_info, (string("http://") + lbos_addr +
9262 "/lbos/watches?format=text").c_str(), NULL, NULL));
9263 if (*lbos_output_orig == NULL)
9264 lbos_output_orig = strdup("");
9265 string lbos_output = *lbos_output_orig;
9266 to_find.push_back("/lbostest");
9267 to_find.push_back("/lbostest1");
9268
9269 unsigned int i = 0;
9270 for (i = 0; i < to_find.size(); ++i) {
9271 WRITE_LOG("Trying to_find[" << i << "] = " << to_find[i]);
9272 while (start != string::npos) {
9273 start = lbos_output.find(to_find[i] + "\t", start);
9274 if (start == string::npos)
9275 break;
9276 // We already know service name since we searched for it.
9277 start = lbos_output.find("\t", start); //skip service name
9278 start += 1; //skip \t
9279 // Next, we extract version.
9280 end = lbos_output.find("\t", start); //version
9281 string version = lbos_output.substr(start, end - start);
9282 // Now we extract ip
9283 start = end + 1; //skip \t
9284 end = lbos_output.find("\t", start); //skip ip
9285 string ip = lbos_output.substr(start, end - start);
9286 /* Make sure that it is IP, not host name */
9287 ip = CSocketAPI::HostPortToString(CSocketAPI::gethostbyname(ip), 0);
9288 // Now we extract port
9289 start = end + 1; //skip "\t"
9290 end = lbos_output.find("\t", start);
9291 unsigned short port =
9292 NStr::StringToInt(lbos_output.substr(start, end - start));
9293 // We skip healthcheck
9294 start = end + 1; //skip \t
9295 end = lbos_output.find("\t", start);
9296 // Check if service is announced are just hangs until being deleted
9297 start = end + 1; //skip \t
9298 end = lbos_output.find("\t", start);
9299 string is_announced = lbos_output.substr(start, end - start);
9300 if (!is_enabled || is_announced == "true") {
9301 SServer node;
9302 node.host = CSocketAPI::gethostbyname(ip);
9303 node.port = port;
9304 node.service = to_find[i];
9305 node.version = version;
9306 nodes.push_back(node);
9307 }
9308 }
9309 start = 0; // reset search for the next service
9310 }
9311 return nodes;
9312 }
9313
9314
9315 #ifdef DEANNOUNCE_ALL_BEFORE_TEST
9316 /** Remove from ZooKeeper only those services which have name specified in
9317 * special array (this array is defined inside this function) and are
9318 * based on current host. We do not remove servers that are based on another
9319 * host not to interfere with other test applications. And we do not touch
9320 * servers with other names that are not related to our test */
s_ClearZooKeeper()9321 static void s_ClearZooKeeper()
9322 {
9323 vector<SServer> nodes = s_GetAnnouncedServers(true);
9324 vector<SServer>::iterator node;
9325 for (node = nodes.begin(); node != nodes.end(); node++) {
9326 string host = CSocketAPI::HostPortToString(node->host, 0);
9327 if (host == s_GetMyIP()) {
9328 try {
9329 s_DeannounceCPP(node->service, node->version, host, node->port);
9330 }
9331 catch (const CLBOSException&) {
9332 }
9333 }
9334 }
9335 }
9336 #endif /* DEANNOUNCE_ALL_BEFORE_TEST */
9337
9338
9339 /** Find server in %LBOS%/text/service */
9340 static
s_CheckIfAnnounced(const string & service,const string & version,unsigned short server_port,const string & health_suffix,bool expectedAnnounced,string expected_host)9341 bool s_CheckIfAnnounced(const string& service,
9342 const string& version,
9343 unsigned short server_port,
9344 const string& health_suffix,
9345 bool expectedAnnounced,
9346 string expected_host)
9347 {
9348 WRITE_LOG("Searching for server " << service << ", port " << server_port <<
9349 " and version " << version << " (expected that it does" <<
9350 (expectedAnnounced ? "" : " NOT") << " appear in /text/service");
9351 int wait_msecs = 500;
9352 int max_retries = kDiscoveryDelaySec * 1000 / wait_msecs;
9353 int retries = 0;
9354 bool announced = !expectedAnnounced;
9355 expected_host = expected_host == ""
9356 ?
9357 CSocketAPI::HostPortToString(CSocketAPI::GetLocalHostAddress(), 0)
9358 :
9359 CSocketAPI::HostPortToString(CSocketAPI::gethostbyname(expected_host),0);
9360 MEASURE_TIME_START
9361 while (announced != expectedAnnounced && retries < max_retries) {
9362 announced = false;
9363 if (retries > 0) { /* for the first cycle we do not sleep */
9364 SleepMilliSec(wait_msecs);
9365 }
9366 WRITE_LOG("Searching for server " << service <<
9367 ", port " << server_port <<
9368 " and version " << version <<
9369 " (expected that it does" <<
9370 (expectedAnnounced ? "" : " NOT") <<
9371 " appear in /text/service " << ". Retry #" << retries);
9372 vector<SServer> nodes = s_GetAnnouncedServers(true);
9373 vector<SServer>::iterator node;
9374 for (node = nodes.begin(); node != nodes.end(); node++) {
9375 string host = CSocketAPI::HostPortToString(node->host, 0);
9376 if (expected_host == host && node->port == server_port &&
9377 node->version == version && node->service == service)
9378 {
9379 announced = true;
9380 break;
9381 }
9382 }
9383 retries++;
9384 }
9385 MEASURE_TIME_FINISH
9386 WRITE_LOG("Server " << service << " with port " << server_port <<
9387 " and version " << version << " was" <<
9388 (announced ? "" : " NOT") << " found int /text/service after " <<
9389 time_elapsed << " seconds (expected to" <<
9390 (expectedAnnounced ? "" : " NOT") << " find it).");
9391 return announced;
9392 }
9393
9394
9395 /** A simple construction that returns "Thread n: " when n is not -1,
9396 * and returns "" (empty string) when n is -1. */
s_PrintThreadNum()9397 static string s_PrintThreadNum() {
9398 stringstream ss;
9399 CTime cl(CTime::eCurrent, CTime::eLocal);
9400
9401 ss << cl.AsString("h:m:s.l ");
9402 int* p_val = s_Tls->GetValue();
9403 if (p_val != NULL) {
9404 if (*p_val == kMainThreadNumber ) {
9405 ss << "Main thread: ";
9406 } else if (*p_val == kHealthThreadNumber ) {
9407 ss << "H/check thread: ";
9408 } else
9409 ss << "Thread " << *p_val << ": ";
9410 }
9411 return ss.str();
9412 }
9413
s_PrintAnnouncedServers()9414 static void s_PrintAnnouncedServers() {
9415 CORE_LOCK_READ;
9416 int count, i;
9417 stringstream ss;
9418 struct SLBOS_AnnounceHandle_Tag** arr =
9419 g_LBOS_UnitTesting_GetAnnouncedServers();
9420
9421 if (*arr == NULL)
9422 return;
9423 count = g_LBOS_UnitTesting_GetAnnouncedServersNum();
9424
9425 for (i = 0; i < count; i++) {
9426 ss << i << ". " <<
9427 "\t" << (*arr)[i].service << "\t" << (*arr)[i].version <<
9428 "\t" << (*arr)[i].host << ":" << (*arr)[i].port << endl;
9429 }
9430 WRITE_LOG("Announced servers list: \n" << ss.str());
9431 CORE_UNLOCK;
9432 }
9433
9434
9435 /** Get string like "x.x.x" and convert it to SLBOSVersion */
s_ParseVersionString(string version)9436 static SLBOSVersion s_ParseVersionString(string version)
9437 {
9438 SLBOSVersion version_struct;
9439 /* Now we parse version into major.minor.patch */
9440 size_t start, end;
9441 start = 0;
9442 end = version.find(".", start);
9443 if (start == string::npos)
9444 return {0,0,0};
9445 version_struct.major = NStr::StringToInt(version.substr(start, end - start));
9446 start = end + 1; // skip "."
9447 end = version.find(".", start);
9448 version_struct.minor = NStr::StringToInt(version.substr(start, end - start));
9449 start = end + 1; // skip "."
9450 end = version.find(".", start);
9451 version_struct.patch = NStr::StringToInt(version.substr(start, end - start));
9452 return version_struct;
9453 }
9454
9455 /** Get string like "x.x.x, x.x.x, x.x.x,..." and convert it to
9456 * vector<SLBOSVersion> */
s_ParseVersionsString(const string & versions)9457 static vector<SLBOSVersion> s_ParseVersionsString(const string& versions)
9458 {
9459 vector<SLBOSVersion> versions_arr;
9460 /* Now we parse version into major.minor.patch */
9461 size_t start = 0, end = 0;
9462 // if there is something to parse
9463 for( ; versions.substr(start).length() > 0 && end != string::npos; ) {
9464 end = versions.find(",", start);
9465 string version_str = versions.substr(start, end-start);
9466 versions_arr.push_back(s_ParseVersionString(version_str));
9467 start = end + 2; //skip ", "
9468 }
9469 return versions_arr;
9470 }
9471
9472 /** Read version of LBOS.
9473 * @note
9474 * Should be run only once during runtime. Multiple runs can cause undefined
9475 * memory leaks
9476 */
s_ReadLBOSVersion()9477 static string s_ReadLBOSVersion()
9478 {
9479 CConnNetInfo net_info;
9480 size_t version_start = 0, version_end = 0;
9481 CCObjHolder<char> lbos_address(g_LBOS_GetLBOSAddress());
9482 string lbos_addr(lbos_address.Get());
9483 CCObjHolder<char> lbos_output_orig(g_LBOS_UnitTesting_GetLBOSFuncs()->
9484 UrlReadAll(*net_info, (string("http://") + lbos_addr +
9485 "/admin/server_info").c_str(), NULL, NULL));
9486 if (*lbos_output_orig == NULL) // for string constructor not to throw
9487 lbos_output_orig = strdup("");
9488 string lbos_output = *lbos_output_orig;
9489 WRITE_LOG("/admin/server_info output: \r\n" << lbos_output);
9490
9491 /* In the output of LBOS we search for "\"version\" : \"" */
9492 string version_tag = "\"version\" : \"";
9493 version_start = lbos_output.find(version_tag) + version_tag.length();
9494 if (version_start == string::npos)
9495 return "";
9496 version_end = lbos_output.find("\"", version_start);
9497 string version = lbos_output.substr(version_start,
9498 version_end - version_start);
9499 s_LBOSVersion = s_ParseVersionString(version);
9500 return version;
9501 }
9502
9503
9504 /** Check if LBOS has version compatible with current test.
9505 * @param[in] versions_arr
9506 * Array of versions that goes "from, till, from, till, ...". If array ends
9507 * with "from" element, it means that there is no maximum LBOS version for
9508 * the test. Details: if LBOS version equals one of "from" versions,
9509 * test is enabled, if LBOS version equals one of "till" versions - test is
9510 * disabled. If versions_arr has no elements, test is enabled. Elements MUST
9511 * be ascending, e.g. "1.0.0, 1.0.2, 0.0.1, 0.0.2" is invalid input
9512 */
s_CheckTestVersion(vector<SLBOSVersion> versions_arr)9513 bool s_CheckTestVersion(vector<SLBOSVersion> versions_arr)
9514 {
9515 if (versions_arr.size() == 0)
9516 return true;
9517 bool active = false;
9518 bool from_till = false; /* false - from version, true - till version */
9519 for (size_t i = 0; i < versions_arr.size(); i++) {
9520 if (from_till) { /* till version */
9521 if (versions_arr[i] <= s_LBOSVersion) {
9522 active = false;
9523 } else {
9524 break;
9525 }
9526 } else { /* from version */
9527 if (versions_arr[i] <= s_LBOSVersion) {
9528 active = true;
9529 } else {
9530 break;
9531 }
9532 }
9533 from_till = !from_till;
9534 }
9535 return active;
9536 }
9537
9538 #endif /* CONNECT___TEST_NCBI_LBOS__HPP*/
9539