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, &params)) {
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