1 /* $Id: coretest.cpp 609466 2020-06-02 15:55:19Z vasilche $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Denis Vakatov
27 *
28 * File Description:
29 * TEST for: NCBI C++ core API
30 *
31 */
32
33 #include <ncbi_pch.hpp>
34 #include <corelib/ncbiapp.hpp>
35 #include <corelib/ncbienv.hpp>
36 #include <corelib/ncbireg.hpp>
37 #include <algorithm>
38 #include <unordered_map>
39
40 #define BOOST_AUTO_TEST_MAIN
41 #include <corelib/test_boost.hpp>
42
43 #include <common/test_assert.h> /* This header must go last */
44
45 // This is to use the ANSI C++ standard templates without the "std::" prefix
46 // and to use NCBI C++ entities without the "ncbi::" prefix
47 USING_NCBI_SCOPE;
48
49
50 /////////////////////////////////////////////////////////////////////////////
51 // Start-up (cmd.-line args, config file)
52
BOOST_AUTO_TEST_CASE(TestStartup)53 BOOST_AUTO_TEST_CASE(TestStartup)
54 {
55 // Command-line arguments
56 SIZE_TYPE n_args = CNcbiApplication::Instance()->GetArguments().Size();
57 NcbiCout << NcbiEndl << "Total # of CMD.-LINE ARGS: "
58 << n_args << NcbiEndl;
59 for (SIZE_TYPE i = 0; i < n_args; i++) {
60 NcbiCout << " [" << i << "] = \""
61 << CNcbiApplication::Instance()->GetArguments()[i]
62 << "\"" << NcbiEndl;
63 }
64 NcbiCout << NcbiEndl;
65
66 // Config.file (registry) content
67 const CNcbiRegistry& reg = CNcbiApplication::Instance()->GetConfig();
68 NcbiCout << "REGISTRY (loaded from config file):" << NcbiEndl;
69 if ( reg.Empty() ) {
70 NcbiCout << " <empty>" << NcbiEndl;
71 } else {
72 reg.Write(NcbiCout);
73 }
74 NcbiCout << NcbiEndl;
75 }
76
77
78 /////////////////////////////////////////////////////////////////////////////
79 // Diagnostics
80 //
81
82 class CNcbiTestDiag {
83 public:
84 int i;
CNcbiTestDiag(void)85 CNcbiTestDiag(void) { i = 4321; }
86 };
operator <<(CNcbiOstream & os,const CNcbiTestDiag & cntd)87 inline CNcbiOstream& operator <<(CNcbiOstream& os, const CNcbiTestDiag& cntd) {
88 return os << "Output of an serializable class content = " << cntd.i;
89 }
90
91
s_TestDiagHandler(const SDiagMessage & mess)92 static void s_TestDiagHandler(const SDiagMessage& mess)
93 {
94 NcbiCout << "<Installed Handler> " << mess << NcbiEndl;
95 }
96
97
BOOST_AUTO_TEST_CASE(TTestDiag)98 BOOST_AUTO_TEST_CASE(TTestDiag)
99 {
100 CNcbiDiag diag;
101 double d = 123.45;
102
103 SetDiagPostFlag(eDPF_All);
104 diag << "[Unset Diag Stream] Diagnostics double = " << d << Endm;
105 ERR_POST( "[Unset Diag Stream] ERR_POST double = " << d );
106 _TRACE( "[Unset Diag Stream] Trace double = " << d );
107
108 NcbiCout << NcbiEndl
109 << "FLUSHing memory-stored diagnostics (if any):" << NcbiEndl;
110 SIZE_TYPE n_flush = CNcbiApplication::Instance()->FlushDiag(&NcbiCout);
111 NcbiCout << "FLUSHed diag: " << n_flush << " bytes" << NcbiEndl <<NcbiEndl;
112
113 {{
114 CNcbiDiag diagWarning;
115 SetDiagHandler(s_TestDiagHandler, 0, 0);
116 diagWarning << "*Warning* -- must be printed by Installed Handler!";
117 }}
118
119 SetDiagStream(&NcbiCerr);
120 diag << "***ERROR*** THIS MESSAGE MUST NOT BE VISIBLE!!!\n\n";
121 SetDiagStream(0);
122 diag << Endm;
123 diag << "01234";
124
125 SetDiagStream(&NcbiCerr);
126 BOOST_CHECK( IsDiagStream(&NcbiCerr) );
127 BOOST_CHECK( !IsDiagStream(&NcbiCout) );
128 diag << "56789" << Endm;
129 diag << "[Set Diag Stream(cerr)] Diagnostics double = " << d << Endm;
130 ERR_POST("[Set Diag Stream(cerr)] Std.Diag. double = " << d );
131 _TRACE ( "[Set Diag Stream(cerr)] Trace double = " << d );
132
133 CNcbiTestDiag cntd;
134 SetDiagPostLevel(eDiag_Error);
135 diag << Warning << cntd << Endm;
136 SetDiagPostLevel(eDiag_Info);
137 diag << Warning << cntd << Endm;
138
139 diag << Error << "This message has severity \"Info\"" << Reset
140 << Info << "This message has severity \"Info\"" << Endm;
141
142 diag << Critical << "This message has severity \"Critical\"" << Endm;
143
144 diag << Trace << "1This message has severity \"Trace\"" << Endm;
145
146 SetDiagPostFlag(eDPF_All);
147 SetDiagPostPrefix("Foo-Prefix");
148 ERR_POST("This is the most detailed " << "error posting");
149 SetDiagPostPrefix(0);
150 UnsetDiagPostFlag(eDPF_Line);
151 UnsetDiagPostFlag(eDPF_LongFilename);
152 ERR_POST(Warning << "No line #, " << "Short filename, " << "No prefix");
153 _TRACE("_TRACE: must have all possible info in the posted message");
154 UnsetDiagPostFlag(eDPF_Severity);
155 ERR_POST("...and no severity");
156 SetDiagPostFlag(eDPF_Line);
157 SetDiagPostFlag(eDPF_Severity);
158 SetDiagPostPrefix("Bad!!! No Prefix!!!");
159 UnsetDiagPostFlag(eDPF_Prefix);
160 ERR_POST("Short filename, " << "No prefix");
161 UnsetDiagPostFlag(eDPF_All);
162 ERR_POST("This is the least detailed error posting");
163 SetDiagPostFlag(eDPF_All);
164 UnsetDiagPostFlag(eDPF_LongFilename);
165
166 PushDiagPostPrefix("Prefix1");
167 ERR_POST("Message with prefix");
168 PushDiagPostPrefix("Prefix2");
169 ERR_POST("Message with prefixes");
170 PushDiagPostPrefix("Prefix3");
171 ERR_POST("Message with prefixes");
172 PopDiagPostPrefix();
173 ERR_POST("Message with prefixes");
174 PopDiagPostPrefix();
175 PopDiagPostPrefix();
176 PopDiagPostPrefix();
177 {{
178 CDiagAutoPrefix a("AutoPrefix");
179 ERR_POST("Message with auto prefix");
180 }}
181 ERR_POST("Message without prefixes");
182 ERR_POST_EX(8, 0, "Message without prefix");
183 SetDiagPostPrefix(0);
184
185 PushDiagPostPrefix("ERROR");
186 PopDiagPostPrefix();
187 ERR_POST_EX(1, 2, "Message with error code, without prefix");
188
189 PushDiagPostPrefix("ERROR");
190 SetDiagPostPrefix(0);
191 diag << Error << ErrCode(3, 4) << "Message with error code" << Endm;
192
193 UnsetDiagPostFlag(eDPF_DateTime);
194 diag << Warning << "Message without datetime stamp" << Endm;
195 SetDiagPostFlag(eDPF_DateTime);
196
197 IgnoreDiagDieLevel(true);
198 {{
199 CNcbiDiag x_diag;
200 x_diag << Fatal << "Fatal message w/o exit()/abort()!" << Endm;
201 }}
202 IgnoreDiagDieLevel(false);
203
204 CStringException ex(DIAG_COMPILE_INFO, NULL,
205 CStringException::eConvert, "A fake exception", 12345);
206 ERR_POST("A test on reporting of an exception" << ex);
207 }
208
209
210 /////////////////////////////////////////////////////////////////////////////
211
BOOST_AUTO_TEST_CASE(TTestDiag_ErrCodeInfo)212 BOOST_AUTO_TEST_CASE(TTestDiag_ErrCodeInfo)
213 {
214 CNcbiDiag diag;
215 SetDiagStream(&NcbiCout);
216
217 CDiagErrCodeInfo info;
218 SDiagErrCodeDescription desc;
219
220 CNcbiIstrstream is("\
221 # Comment line\n\
222 \n\
223 MODULE coretest\n\
224 \n\
225 $$ DATE, 1 : Short message for error code (1,0)\n\
226 \n\
227 $^ NameOfError, 1, 3 : Short message for error code (1,1)\n\
228 This is a long message for error code (1,1).\n\
229 $^ NameOfWarning, 2, WARNING: Some short text with ':' and ',' characters\n\
230 This is first line of the error explanation.\n\
231 This is second line of the error explanation.\n\
232 \n\
233 $$ PRINT, 9, 2\n\
234 Error with code (9,0).\n\
235 $^ EmptyString, 1, info:Error with subcode 1.\n\
236 $^ BadFormat, 2\n\
237 Message for warning error PRINT_BadFormat.\n\
238 ");
239
240 info.Read(is);
241 info.SetDescription(ErrCode(2,3),
242 SDiagErrCodeDescription("Err 2.3", "Error 2.3"
243 /*, default severity */));
244 info.SetDescription(ErrCode(2,4),
245 SDiagErrCodeDescription("Err 2.4", "Error 2.4",
246 eDiag_Error));
247
248 BOOST_CHECK(info.GetDescription(ErrCode(1,1), &desc));
249 BOOST_CHECK_EQUAL(desc.m_Message, "Short message for error code (1,1)");
250 BOOST_CHECK_EQUAL(desc.m_Explanation, "This is a long message for error code (1,1).");
251 BOOST_CHECK_EQUAL(desc.m_Severity, 3);
252
253 BOOST_CHECK(info.GetDescription(ErrCode(9,0), &desc));
254 BOOST_CHECK_EQUAL(desc.m_Severity, 2);
255 BOOST_CHECK(info.GetDescription(ErrCode(9,1), &desc));
256 BOOST_CHECK_EQUAL(desc.m_Severity, eDiag_Info);
257 BOOST_CHECK(info.GetDescription(ErrCode(9,2), &desc));
258 BOOST_CHECK_EQUAL(desc.m_Severity, 2);
259
260 BOOST_CHECK(info.GetDescription(ErrCode(2,4), &desc));
261 BOOST_CHECK_EQUAL(desc.m_Message, "Err 2.4");
262 BOOST_CHECK_EQUAL(desc.m_Explanation, "Error 2.4");
263 BOOST_CHECK_EQUAL(desc.m_Severity, eDiag_Error);
264
265 BOOST_CHECK(!info.GetDescription(ErrCode(1,3), &desc));
266
267 SetDiagErrCodeInfo(&info, false);
268 SetDiagPostFlag(eDPF_All);
269 SetDiagPostPrefix("Prefix");
270
271 ERR_POST("This message has default severity \"Error\"");
272 ERR_POST_EX(1,1,"This message has severity \"Critical\"");
273
274 diag << ErrCode(1,1) << Info << "This message has severity \"Critical\""
275 << Endm;
276 UnsetDiagPostFlag(eDPF_ErrCodeMessage);
277 diag << ErrCode(1,1) << Info << "This message has severity \"Critical\""
278 << Endm;
279 UnsetDiagPostFlag(eDPF_Prefix);
280 diag << ErrCode(1,1) << Info << "This message has severity \"Critical\""
281 << Endm;
282 UnsetDiagPostFlag(eDPF_ErrCode);
283 UnsetDiagPostFlag(eDPF_ErrCodeUseSeverity);
284 diag << ErrCode(1,1) << Info << "This message has severity \"Info\""
285 << Endm;
286 UnsetDiagPostFlag(eDPF_ErrCodeExplanation);
287 SetDiagPostFlag(eDPF_ErrCodeUseSeverity);
288 diag << ErrCode(1,1) << "This message has severity \"Critical\"" << Endm;
289 SetDiagErrCodeInfo(0);
290 }
291
292
293 /////////////////////////////////////////////////////////////////////////////
294 // Exceptions
295 //
296
TE_runtime(void)297 static void TE_runtime(void) {
298 throw runtime_error("TE_runtime::runtime_error");
299 }
300
TE_none(void)301 static void TE_none(void) THROWS_NONE {
302 return;
303 }
304
TE_logic(void)305 static void TE_logic(void) THROWS((runtime_error,logic_error)) {
306 throw logic_error("TE_logic::logic_error");
307 }
308
309
310 class XXX {
311 string mess;
312 public:
313 XXX(const XXX& x);
314 XXX(const string& m);
315 ~XXX(void);
what(void) const316 const string& what(void) const { return mess; }
317 };
318
XXX(const string & m)319 XXX::XXX(const string& m) : mess(m) {
320 NcbiCerr << "XXX: " << (void*)(this) << NcbiEndl;
321 }
XXX(const XXX & x)322 XXX::XXX(const XXX&x) : mess(x.mess) {
323 NcbiCerr << "XXX(" << (void*)(&x) << "): " << (void*)(this) << NcbiEndl;
324 }
~XXX(void)325 XXX::~XXX(void) {
326 NcbiCerr << "~XXX: " << (void*)(this) << NcbiEndl;
327 }
328
s_ThrowXXX(void)329 static void s_ThrowXXX(void) {
330 NcbiCerr << NcbiEndl << "Throw class XXX" << NcbiEndl;
331 throw XXX("s_ThrowXXX message");
332
333 }
334
BOOST_AUTO_TEST_CASE(TestException_Features)335 BOOST_AUTO_TEST_CASE(TestException_Features)
336 {
337 CNcbiOstream* prevDiag = GetDiagStream();
338 SetDiagStream(&NcbiCout);
339 try {
340 s_ThrowXXX();
341 } catch (XXX& x) {
342 NcbiCerr << "Catch (XXX& x): " << x.what() << NcbiEndl;
343 }
344
345 try {
346 s_ThrowXXX();
347 } catch (XXX x) {
348 NcbiCerr << "Catch (XXX x): " << x.what() << NcbiEndl << NcbiEndl;
349 }
350 SetDiagStream(prevDiag);
351 }
352
353
BOOST_AUTO_TEST_CASE(TestException_Std)354 BOOST_AUTO_TEST_CASE(TestException_Std)
355 {
356 CNcbiOstream* prevDiag = GetDiagStream();
357 SetDiagStream(&NcbiCout);
358 try { TE_runtime(); }
359 catch (runtime_error& e) {
360 NcbiCerr << "CATCH TE_runtime::runtime_error : " << e.what()<<NcbiEndl;
361 }
362
363 try { TE_runtime(); }
364 catch (exception& e) {
365 NcbiCerr << "CATCH TE_runtime::exception " << e.what() << NcbiEndl;
366 }
367
368 try { TE_runtime(); }
369 STD_CATCH ("STD_CATCH TE_runtime ");
370
371 try { TE_runtime(); }
372 catch (logic_error& e) {
373 NcbiCerr << "CATCH TE_runtime::logic_error " << e.what() << NcbiEndl;
374 _TROUBLE; }
375 STD_CATCH_ALL ("STD_CATCH_ALL TE_runtime");
376
377 TE_none();
378
379 try { TE_logic(); }
380 catch (logic_error& e) {
381 NcbiCerr << "CATCH TE_logic " << e.what() << NcbiEndl; }
382 STD_CATCH_ALL ("try { TE_logic(); } SOMETHING IS WRONG!");
383 SetDiagStream(prevDiag);
384 }
385
386
BOOST_AUTO_TEST_CASE(TestException_Aux)387 BOOST_AUTO_TEST_CASE(TestException_Aux)
388 {
389 CNcbiOstream* prevDiag = GetDiagStream();
390 SetDiagStream(&NcbiCout);
391 try {
392 BOOST_CHECK( !strtod("1e-999999", 0) );
393 NCBI_THROW(CErrnoTemplException<CCoreException>,eErrno,
394 "Failed strtod(\"1e-999999\", 0)");
395 }
396 catch (CErrnoTemplException<CCoreException>& e) {
397 NCBI_REPORT_EXCEPTION("TEST CErrnoTemplException<CCoreException> ---> ",e);
398 }
399 try {
400 NCBI_THROW2(CParseTemplException<CCoreException>,eErr,
401 "Failed parsing (at pos. 123)",123);
402 }
403 catch (CException& e) {
404 NCBI_REPORT_EXCEPTION("TEST CParseTemplException<CCoreException> ---> ",e);
405 }
406 catch (...) {
407 // Should never be here
408 _TROUBLE;
409 }
410 SetDiagStream(prevDiag);
411 }
412
BOOST_AUTO_TEST_CASE(TestStreamposConvert)413 BOOST_AUTO_TEST_CASE(TestStreamposConvert)
414 {
415 Int8 p1 = 1;
416 p1 <<= 45;
417
418 CT_POS_TYPE pos = NcbiInt8ToStreampos(p1);
419 Int8 p2 = NcbiStreamposToInt8(pos);
420
421 if ( sizeof(CT_POS_TYPE) < sizeof(Int8) ||
422 sizeof(CT_OFF_TYPE) < sizeof(Int8) ) {
423 ERR_POST(Warning <<
424 "Large streams are not supported, skipping the test");
425 return;
426 }
427 BOOST_CHECK(p1 == p2);
428 BOOST_CHECK(p1 && p2);
429 }
430
431
432 #if 0
433 BOOST_AUTO_TEST_CASE(TestException)
434 {
435 SetDiagStream(&NcbiCout);
436
437 TestException_Features();
438 TestException_Std();
439 TestException_Aux();
440 TestStreamposConvert();
441 }
442 #endif
443
444 /////////////////////////////////////////////////////////////////////////////
445
BOOST_AUTO_TEST_CASE(TestException_AuxTrace)446 BOOST_AUTO_TEST_CASE(TestException_AuxTrace)
447 {
448 try {
449 BOOST_CHECK( !strtod("1e-999999", 0) );
450 NCBI_THROW(CErrnoTemplException<CCoreException>,eErrno,
451 "Failed strtod('1e-999999', 0)");
452 }
453 catch (CErrnoTemplException<CCoreException>& e) {
454 NCBI_REPORT_EXCEPTION("throw CErrnoTemplException<CCoreException> ---> ",e);
455 }
456
457 try {
458 try {
459 // BW___WS53
460 // Sigh. WorkShop 5.3 is stupid, and complains about
461 // const char* vs. const char[15] without this cast.
462 THROW_TRACE_SIMPLE((const char*) "Throw a string");
463 } catch (const char* /*e*/) {
464 RETHROW_TRACE;
465 }
466 } catch (const char* /*e*/) {
467 }
468
469 try {
470 THROW_TRACE_SIMPLE(bad_alloc());
471 }
472 STD_CATCH ("THROW_TRACE_SIMPLE bad_alloc ---> ");
473
474 try {
475 THROW_TRACE_ARGS(runtime_error, "Some message...");
476 }
477 STD_CATCH ("THROW_TRACE_ARGS runtime_error ---> ");
478
479 try {
480 NCBI_THROW2(CParseTemplException<CCoreException>,eErr,
481 "Failed parsing (at pos. 123)", 123);
482 }
483 catch (CException& e) {
484 NCBI_REPORT_EXCEPTION("throw CParseTemplException<CCoreException> ---> ",e);
485 }
486 }
487
488
489 /////////////////////////////////////////////////////////////////////////////
490 // I/O stream extensions
491 //
492
BOOST_AUTO_TEST_CASE(TestIostream)493 BOOST_AUTO_TEST_CASE(TestIostream)
494 {
495 CNcbiIstrstream is("abc\r\nx0123456789\ny012345\r \tcba");
496 string str;
497
498 while (NcbiGetline(is, str, "\r\n")) {
499 NcbiCout << str << NcbiEndl;
500 BOOST_CHECK(!str.empty());
501 }
502 is.clear();
503 is.seekg(0, IOS_BASE::beg);
504
505 NcbiGetline(is, str, '\n');
506 BOOST_CHECK( is.good() );
507 BOOST_CHECK( str.compare("abc\r") == 0 );
508
509 is >> str;
510 BOOST_CHECK( is.good() );
511 BOOST_CHECK( str.compare("x0123456789") == 0 );
512
513 is >> str;
514 BOOST_CHECK( is.good() );
515 BOOST_CHECK( str.compare("y012345") == 0 );
516
517 is >> str;
518 BOOST_CHECK( is.eof() );
519 BOOST_CHECK( str.compare("cba") == 0 );
520
521 is >> str;
522 BOOST_CHECK( !is.good() );
523
524 is.clear();
525 is >> str;
526 BOOST_CHECK( !is.good() );
527
528 str = "0 1 2 3 4 5\n6 7 8 9";
529 NcbiCout << "String output: " << str << NcbiEndl;
530
531 const char kNullDev[] =
532 #ifdef NCBI_OS_MSWIN
533 "NUL"
534 #else
535 "/dev/null"
536 #endif /*NCBI_OS_MSWIN*/
537 ;
538 CNcbiOfstream ofs(kNullDev);
539 CNcbiIfstream ifs(kNullDev);
540
541 BOOST_CHECK(NcbiStreamCopy(ofs, ifs));
542
543 NcbiCout << "NcbiStreamCopy() test passed" << NcbiEndl;
544 }
545
546
547
548 /////////////////////////////////////////////////////////////////////////////
549 // Registry
550 //
551
BOOST_AUTO_TEST_CASE(TestRegistry)552 BOOST_AUTO_TEST_CASE(TestRegistry)
553 {
554 CNcbiRegistry reg;
555 CConstRef<IRegistry> env_reg
556 = reg.FindByName(CNcbiRegistry::sm_EnvRegName);
557 if (env_reg.Empty()) {
558 ERR_POST("Environment-based subregistry missing");
559 } else {
560 reg.Remove(*env_reg);
561 }
562 BOOST_CHECK( reg.Empty() );
563
564 list<string> sections;
565 reg.EnumerateSections(§ions);
566 BOOST_CHECK( sections.empty() );
567
568 list<string> entries;
569 reg.EnumerateEntries(kEmptyStr, &entries);
570 BOOST_CHECK( entries.empty() );
571
572 // Compose a test registry
573 BOOST_CHECK( reg.Set("Section0", "Name01", "Val01_BAD!!!") );
574 BOOST_CHECK( reg.Set("Section1 ", "\nName11", "Val11_t") );
575 BOOST_CHECK( !reg.Empty() );
576 BOOST_CHECK( reg.Get(" Section1", "Name11\t") == "Val11_t" );
577 BOOST_CHECK( reg.Get("Section1", "Name11",
578 CNcbiRegistry::ePersistent).empty() );
579 BOOST_CHECK( reg.Set("Section1", "Name11", "Val11_t") );
580 BOOST_CHECK( !reg.Set("Section1", "Name11", "Val11_BAD!!!",
581 CNcbiRegistry::eNoOverride) );
582
583 BOOST_CHECK( reg.Set(" Section2", "\nName21 ", "Val21",
584 CNcbiRegistry::ePersistent |
585 CNcbiRegistry::eNoOverride) );
586 BOOST_CHECK( reg.Set("Section2", "Name21", "Val21_t") );
587 BOOST_CHECK( !reg.Empty() );
588 BOOST_CHECK( reg.Set("Section3", "Name31", "Val31_t") );
589
590 BOOST_CHECK( reg.Get(" \nSection1", " Name11 ") == "Val11_t" );
591 BOOST_CHECK( reg.Get("Section2", "Name21", CNcbiRegistry::ePersistent) ==
592 "Val21" );
593 BOOST_CHECK( reg.Get(" Section2", " Name21\n") == "Val21_t" );
594 BOOST_CHECK( reg.Get("SectionX", "Name21").empty() );
595
596 BOOST_CHECK( reg.Set("Section4", "Name41", "Val410 Val411 Val413",
597 CNcbiRegistry::ePersistent) );
598 BOOST_CHECK(!reg.Set("Sect ion4", "Name41", "BAD1",
599 CNcbiRegistry::ePersistent) );
600 BOOST_CHECK(!reg.Set("Section4", "Na me41", "BAD2") );
601 BOOST_CHECK( reg.Set("SECTION4", "Name42", "V420 V421\nV422 V423 \"",
602 CNcbiRegistry::ePersistent) );
603 BOOST_CHECK( reg.Set("Section4", "NAME43",
604 " \tV430 V431 \n V432 V433 ",
605 CNcbiRegistry::ePersistent) );
606 BOOST_CHECK( reg.Set("\tSection4", "Name43T",
607 " \tV430 V431 \n V432 V433 ",
608 CNcbiRegistry::ePersistent | CNcbiRegistry::eTruncate) );
609 BOOST_CHECK( reg.Set("Section4", "Name44", "\n V440 V441 \r\n",
610 CNcbiRegistry::ePersistent) );
611 BOOST_CHECK( reg.Set("\r Section4", " \t\rName45", "\r\n V450 V451 \n ",
612 CNcbiRegistry::ePersistent) );
613 BOOST_CHECK( reg.Set("Section4 \n", " Name46 ", "\n\nV460\" \n \t \n\t",
614 CNcbiRegistry::ePersistent) );
615 BOOST_CHECK( reg.Set(" Section4", "Name46T", "\n\nV460\" \n \t \n\t",
616 CNcbiRegistry::ePersistent | CNcbiRegistry::eTruncate) );
617 BOOST_CHECK( reg.Set("Section4", "Name47", "470\n471\\\n 472\\\n473\\",
618 CNcbiRegistry::ePersistent) );
619 BOOST_CHECK( reg.Set("Section4", "Name47T", "470\n471\\\n 472\\\n473\\",
620 CNcbiRegistry::ePersistent | CNcbiRegistry::eTruncate) );
621 string xxx("\" V481\" \n\"V482 ");
622 BOOST_CHECK( reg.Set("Section4", "Name48", xxx, CNcbiRegistry::ePersistent) );
623
624 BOOST_CHECK( reg.Set("Section5", "Name51", "Section5/Name51",
625 CNcbiRegistry::ePersistent) );
626 BOOST_CHECK( reg.Set("_Section_5", "Name51", "_Section_5/Name51",
627 CNcbiRegistry::ePersistent) );
628 BOOST_CHECK( reg.Set("_Section_5_", "_Name52", "_Section_5_/_Name52",
629 CNcbiRegistry::ePersistent) );
630 BOOST_CHECK( reg.Set("_Section_5_", "Name52", "_Section_5_/Name52",
631 CNcbiRegistry::ePersistent) );
632 BOOST_CHECK( reg.Set("_Section_5_", "_Name53_", "_Section_5_/_Name53_",
633 CNcbiRegistry::ePersistent) );
634 BOOST_CHECK( reg.Set("Section-5.6", "Name-5.6", "Section-5.6/Name-5.6",
635 CNcbiRegistry::ePersistent) );
636 BOOST_CHECK( reg.Set("-Section_5", ".Name.5-3", "-Section_5/.Name.5-3",
637 CNcbiRegistry::ePersistent) );
638
639
640 // Dump
641 CNcbiOstrstream os;
642 BOOST_CHECK ( reg.Write(os) );
643 string os_string = CNcbiOstrstreamToString(os);
644 const char* os_str = os_string.c_str();
645 NcbiCerr << "\nRegistry:\n" << os_str << NcbiEndl;
646
647 // "Persistent" load
648 CNcbiIstrstream is1(os_str);
649 CNcbiRegistry reg1(is1);
650 BOOST_CHECK( reg1.Get("Section2", "Name21", CNcbiRegistry::ePersistent) ==
651 "Val21" );
652 BOOST_CHECK( reg1.Get("Section2", "Name21") == "Val21" );
653 BOOST_CHECK( reg1.Set("Section2", "Name21", NcbiEmptyString) );
654 BOOST_CHECK( !reg1.Set("Section2", "Name21", NcbiEmptyString,
655 CNcbiRegistry::ePersistent |
656 CNcbiRegistry::eNoOverride) );
657 BOOST_CHECK( !reg1.Empty() );
658 BOOST_CHECK( reg1.Set("Section2", "Name21", NcbiEmptyString,
659 CNcbiRegistry::ePersistent) );
660
661 // "Transient" load
662 CNcbiIstrstream is2(os_str);
663 CNcbiRegistry reg2(is2, CNcbiRegistry::eTransient);
664 BOOST_CHECK( reg2.Get("Section2", "Name21",
665 CNcbiRegistry::ePersistent).empty() );
666 BOOST_CHECK( reg2.Get("Section2", "Name21") == "Val21" );
667 BOOST_CHECK( !reg2.Set("Section2", "Name21", NcbiEmptyString,
668 CNcbiRegistry::ePersistent) );
669 BOOST_CHECK( !reg2.Set("Section2", "Name21", NcbiEmptyString,
670 CNcbiRegistry::ePersistent |
671 CNcbiRegistry::eNoOverride) );
672 BOOST_CHECK( !reg2.Empty() );
673 BOOST_CHECK( reg2.Set("Section2", "Name21", NcbiEmptyString) );
674
675
676 BOOST_CHECK( reg.Get("Sect ion4 ", "Name41 ").empty() );
677 BOOST_CHECK( reg.Get("Section4 ", "Na me41 ").empty() );
678
679 BOOST_CHECK( reg.Get("Section4 ", "Name41 ") == "Val410 Val411 Val413" );
680 BOOST_CHECK( reg.Get("Section4", " Name42") == "V420 V421\nV422 V423 \"" );
681 BOOST_CHECK( reg.Get("Section4", "Name43") == " \tV430 V431 \n V432 V433 ");
682 BOOST_CHECK( reg.Get("Section4", "Name43T") == "V430 V431 \n V432 V433" );
683 BOOST_CHECK( reg.Get("Section4", " Name44") == "\n V440 V441 \r\n" );
684 BOOST_CHECK( reg.Get(" SecTIon4", "Name45") == "\r\n V450 V451 \n " );
685 BOOST_CHECK( reg.Get("SecTion4 ", "Name46") == "\n\nV460\" \n \t \n\t" );
686 BOOST_CHECK( reg.Get("Section4", "NaMe46T") == "\n\nV460\" \n \t \n" );
687 BOOST_CHECK( reg.Get(" Section4", "Name47") == "470\n471\\\n 472\\\n473\\" );
688 BOOST_CHECK( reg.Get("Section4 ", "NAme47T") == "470\n471\\\n 472\\\n473\\" );
689 BOOST_CHECK( reg.Get("Section4", "Name48") == xxx );
690
691 BOOST_CHECK( reg2.Get("Section4", "Name41") == "Val410 Val411 Val413" );
692 BOOST_CHECK( reg2.Get("Section4", "Name42") == "V420 V421\nV422 V423 \"" );
693 BOOST_CHECK( reg2.Get("Section4", "Name43") == " \tV430 V431 \n V432 V433 ");
694 BOOST_CHECK( reg2.Get("Section4", "Name43T") == "V430 V431 \n V432 V433" );
695 BOOST_CHECK( reg2.Get("Section4", "Name44") == "\n V440 V441 \r\n" );
696 BOOST_CHECK( reg2.Get("Section4", "NaMe45") == "\r\n V450 V451 \n " );
697 BOOST_CHECK( reg2.Get("SecTIOn4", "NAme46") == "\n\nV460\" \n \t \n\t" );
698 BOOST_CHECK( reg2.Get("Section4", "Name46T") == "\n\nV460\" \n \t \n" );
699 BOOST_CHECK( reg2.Get("Section4", "Name47") == "470\n471\\\n 472\\\n473\\" );
700 BOOST_CHECK( reg2.Get("Section4", "Name47T") == "470\n471\\\n 472\\\n473\\" );
701 BOOST_CHECK( reg2.Get("Section4", "Name48") == xxx );
702
703 BOOST_CHECK( reg2.Get(" Section5", "Name51 ") == "Section5/Name51" );
704 BOOST_CHECK( reg2.Get("_Section_5", " Name51") == "_Section_5/Name51" );
705 BOOST_CHECK( reg2.Get(" _Section_5_", " _Name52") == "_Section_5_/_Name52");
706 BOOST_CHECK( reg2.Get("_Section_5_ ", "Name52") == "_Section_5_/Name52");
707 BOOST_CHECK( reg2.Get("_Section_5_", "_Name53_ ") == "_Section_5_/_Name53_" );
708 BOOST_CHECK( reg2.Get(" Section-5.6", "Name-5.6 ") == "Section-5.6/Name-5.6");
709 BOOST_CHECK( reg2.Get("-Section_5", ".Name.5-3") == "-Section_5/.Name.5-3");
710
711 // Printout of the whole registry content
712 BOOST_CHECK( reg.Set("Section0", "Name01", "") );
713 reg.EnumerateSections(§ions);
714 BOOST_CHECK( find(sections.begin(), sections.end(), "Section0")
715 == sections.end() );
716 BOOST_CHECK( find(sections.begin(), sections.end(), "Section1")
717 != sections.end() );
718 BOOST_CHECK( !sections.empty() );
719 NcbiCout << "\nRegistry Content:\n";
720 for (list<string>::const_iterator itSection = sections.begin();
721 itSection != sections.end(); itSection++) {
722 NcbiCout << "Section: " << *itSection << NcbiEndl;
723 reg.EnumerateEntries(*itSection, &entries);
724 for (list<string>::const_iterator itEntry = entries.begin();
725 itEntry != entries.end(); itEntry++) {
726 NcbiCout << " Entry: " << *itEntry << NcbiEndl;
727 NcbiCout << " Default: "
728 << reg.Get(*itSection, *itEntry) << NcbiEndl;
729 NcbiCout << " Persistent: "
730 << reg.Get(*itSection, *itEntry,
731 CNcbiRegistry::ePersistent) << NcbiEndl;
732 }
733 }
734
735 reg.Clear();
736 BOOST_CHECK( reg.Empty() );
737
738 // Test read/write registry
739
740 NcbiCout << endl;
741 NcbiCout << "---------------------------------------------------" << endl;
742
743 CNcbiIstrstream is("\n\
744 ############################################\n\
745 #\n\
746 # Registry file comment\n\
747 #\n\
748 ############################################\n\
749 \n\
750 ; comment for section1\n\
751 \n\
752 [section1]\n\
753 ; This is a comment for n11\n\
754 #\n\
755 # File comment also\n\
756 #\n\
757 n11 = value11\n\
758 \n\
759 ; This is a comment for n12 line 1\n\
760 ; This is a comment for n12 line 2\n\
761 \n\
762 n12 = value12\n\
763 \n\
764 ; This is a comment for n13\n\
765 n13 = value13\n\
766 ; new comment for n13\n\
767 n13 = new_value13\n\
768 \n\
769 [ section2 ]\n\
770 ; This is a comment for n21\n\
771 n21 = value21\n\
772 ; This is a comment for n22\n\
773 n22 = value22\n\
774 [section3]\n\
775 n31 = value31\n\
776 ");
777
778 reg.Read(is);
779 reg.Write(NcbiCout);
780 NcbiCout << "---------------------------------------------------" << endl;
781 NcbiCout << "File comment:" << endl;
782 NcbiCout << reg.GetComment() << endl;
783 NcbiCout << "Section comment:" << endl;
784 NcbiCout << reg.GetComment("section1") << endl;
785 NcbiCout << "Entry comment:" << endl;
786 NcbiCout << reg.GetComment("section1","n12") << endl;
787
788 reg.SetComment(" new comment\n# for registry\n\n # ...\n\n\n");
789 reg.SetComment(";new comment for section1\n","section1");
790 reg.SetComment("new comment for section3","section3");
791 reg.SetComment("new comment for entry n11","section1","n11");
792 reg.SetComment(" ; new comment for entry n31","section3","n31");
793 reg.SetComment("","section2","n21");
794
795 NcbiCout << "---------------------------------------------------" << endl;
796 reg.Write(NcbiCout);
797 NcbiCout << "---------------------------------------------------" << endl;
798 }
799
800
801 /////////////////////////////////////////////////////////////////////////////
802
BOOST_AUTO_TEST_CASE(TestThrowTrace)803 BOOST_AUTO_TEST_CASE(TestThrowTrace)
804 {
805 SetDiagTrace(eDT_Enable);
806 NcbiCerr << "The following lines should be equal pairs:" << NcbiEndl;
807 try {
808 THROW_TRACE_ARGS(runtime_error, "Message");
809 }
810 catch (...) {
811 CDiagCompileInfo dci(__FILE__, __LINE__ - 3, NCBI_CURRENT_FUNCTION);
812 CNcbiDiag(dci, eDiag_Trace) << "runtime_error: Message";
813 }
814 string mess = "ERROR";
815 try {
816 THROW_TRACE_ARGS(runtime_error, mess);
817 }
818 catch (...) {
819 CDiagCompileInfo dci(__FILE__, __LINE__ - 3, NCBI_CURRENT_FUNCTION);
820 CNcbiDiag(dci, eDiag_Trace) << "runtime_error: ERROR";
821 }
822 int i = 123;
823 try {
824 THROW_TRACE_SIMPLE(i);
825 }
826 catch (...) {
827 CDiagCompileInfo dci(__FILE__, __LINE__ - 3, NCBI_CURRENT_FUNCTION);
828 CNcbiDiag(dci, eDiag_Trace) << "i: 123";
829 }
830 SetDiagTrace(eDT_Default);
831 }
832
833 #include <corelib/ncbiobj.hpp>
834
835 class CObjectInt : public CObject
836 {
837 public:
CObjectInt()838 CObjectInt() : m_Int(0) {}
CObjectInt(int i)839 CObjectInt(int i) : m_Int(i) {}
840 int m_Int;
841 };
842
843 class IInterface
844 {
845 public:
~IInterface()846 virtual ~IInterface() {}
847 virtual void foo() = 0;
848 virtual void bar() const = 0;
849 };
850
851 class CImplementation : public CObject, public IInterface
852 {
853 public:
~CImplementation()854 virtual ~CImplementation() {}
foo()855 virtual void foo() {}
bar() const856 virtual void bar() const {}
857 };
858
859
860 /////////////////////////////////////////////////////////////////////////////
861
BOOST_AUTO_TEST_CASE(TestHeapStack)862 BOOST_AUTO_TEST_CASE(TestHeapStack)
863 {
864 SetDiagTrace(eDT_Enable);
865 {
866 NcbiCerr << "Test CObjectInt in stack:" << NcbiEndl;
867 CObjectInt stackObj;
868 BOOST_CHECK(!stackObj.CanBeDeleted());
869 }
870 {
871 NcbiCerr << "Test CObjectInt on heap:" << NcbiEndl;
872 CObjectInt* heapObj = new CObjectInt();
873 BOOST_CHECK(heapObj->CanBeDeleted());
874 delete heapObj;
875 }
876 {
877 NcbiCerr << "Test static CObjectInt:" << NcbiEndl;
878 static CObjectInt staticObj;
879 BOOST_CHECK(!staticObj.CanBeDeleted());
880 }
881 {
882 NcbiCerr << "Test CRef on CObjectInt on heap:" << NcbiEndl;
883 CRef<CObjectInt> objRef(new CObjectInt());
884 BOOST_CHECK(objRef->CanBeDeleted());
885 }
886 {
887 NcbiCerr << "Test CObject in stack:" << NcbiEndl;
888 CObject stackObj;
889 BOOST_CHECK(!stackObj.CanBeDeleted());
890 }
891 {
892 NcbiCerr << "Test CObject on heap:" << NcbiEndl;
893 CObject* heapObj = new CObject();
894 BOOST_CHECK(heapObj->CanBeDeleted());
895 delete heapObj;
896 }
897 {
898 NcbiCerr << "Test static CObject:" << NcbiEndl;
899 static CObject staticObj;
900 BOOST_CHECK(!staticObj.CanBeDeleted());
901 }
902 {
903 NcbiCerr << "Test CRef on CObject on heap:" << NcbiEndl;
904 CRef<CObject> objRef(new CObject());
905 BOOST_CHECK(objRef->CanBeDeleted());
906 }
907 SetDiagTrace(eDT_Default);
908
909 CIRef<IInterface> iref(new CImplementation);
910 iref->foo();
911 iref->bar();
912 CConstIRef<IInterface> ciref(iref);
913 ciref->bar();
914 ciref = iref;
915 ciref->bar();
916 ciref = null;
917 ciref = iref;
918 ciref->bar();
919 ciref = new CImplementation;
920 ciref->bar();
921 }
922
923
924 #ifdef NCBI_COMPILER_MIPSPRO
925 # define NO_EMPTY_BASE_OPTIMIZATION
926 #endif
927
928 class CEmpty
929 {
930 };
931
932 class CSubclass : CEmpty
933 {
934 protected:
935 int i;
936 };
937
938
939 template<class A, class B>
940 class CObjectSizeTester
941 {
942 public:
Test(bool & error)943 static void Test(bool& error)
944 {
945 size_t a_size = sizeof(A);
946 size_t b_size = sizeof(B);
947 if ( a_size != b_size ) {
948 NcbiCerr
949 << "Object size test failed:" << NcbiEndl
950 << " sizeof(" << typeid(A).name() << ") = " << a_size
951 << NcbiEndl
952 << " sizeof(" << typeid(B).name() << ") = " << b_size
953 << NcbiEndl;
954 error = true;
955 }
956 }
957 };
958
959
960 /////////////////////////////////////////////////////////////////////////////
961
BOOST_AUTO_TEST_CASE(TestObjectSizes)962 BOOST_AUTO_TEST_CASE(TestObjectSizes)
963 {
964 NcbiCout <<
965 "Check if compiler supports empty-base optimization" << NcbiEndl;
966 // check if it works
967 bool error = false;
968 CObjectSizeTester<CSubclass, int>::Test(error);
969 CObjectSizeTester<CRef<CObject>, CObject*>::Test(error);
970 CObjectSizeTester<CConstRef<CObject>, const CObject*>::Test(error);
971 CObjectSizeTester<CMutexGuard, CMutexGuard::resource_type*>::Test(error);
972 if ( !error ) {
973 NcbiCout <<
974 "This compiler supports empty-base optimization!" << NcbiEndl;
975 }
976 else {
977 NcbiCerr <<
978 "Test for empty-base optimization failed!" << NcbiEndl;
979 #ifndef NO_EMPTY_BASE_OPTIMIZATION
980 BOOST_CHECK(!error);
981 #endif
982 }
983 }
984
985
986 /////////////////////////////////////////////////////////////////////////////
987
988
989 template<class Src, class Dst,
990 class SrcObj = typename Src::TObjectType,
991 class DstObj = typename Dst::TObjectType>
s_TestCopyMove()992 void s_TestCopyMove()
993 {
994 NcbiCout << "TestCopyMove: "<<typeid(Src).name()<<" -> "<<typeid(Dst).name()
995 << NcbiEndl;
996
997 BOOST_CHECK((std::is_constructible<Dst, const Dst&>::value));
998 BOOST_CHECK((std::is_constructible<Dst, const Src&>::value));
999 BOOST_CHECK((std::is_same<Src, Dst>::value ||
1000 !std::is_constructible<Src, const Dst&>::value));
1001
1002 BOOST_CHECK((std::is_constructible<Dst, Dst&&>::value));
1003 BOOST_CHECK((std::is_constructible<Dst, Src&&>::value));
1004 BOOST_CHECK((std::is_same<Src, Dst>::value ||
1005 !std::is_constructible<Src, Dst&&>::value));
1006
1007 BOOST_CHECK((std::is_convertible<const Dst&, Dst>::value));
1008 BOOST_CHECK((std::is_convertible<const Src&, Dst>::value));
1009 BOOST_CHECK((std::is_same<Src, Dst>::value ||
1010 !std::is_convertible<const Dst&, Src>::value));
1011
1012 BOOST_CHECK((std::is_convertible<Dst&&, Dst>::value));
1013 BOOST_CHECK((std::is_convertible<Src&&, Dst>::value));
1014 BOOST_CHECK((std::is_same<Src, Dst>::value ||
1015 !std::is_convertible<Dst&&, Src>::value));
1016
1017 Src obj0(new SrcObj());
1018 BOOST_REQUIRE(obj0);
1019 BOOST_REQUIRE(dynamic_cast<const CObject*>(obj0.GetPointerOrNull()));
1020 BOOST_CHECK(dynamic_cast<const CObject*>(obj0.GetPointerOrNull())->ReferencedOnlyOnce());
1021
1022 // same type
1023 Src obj1 = obj0; // copy constructor !empty
1024 BOOST_CHECK(obj1);
1025 BOOST_CHECK(obj1 == obj0);
1026
1027 Src obj2; obj2 = obj0; // assignment !empty -> empty
1028 BOOST_CHECK(obj2);
1029 BOOST_CHECK(!(obj2 != obj0));
1030
1031 Src obj3 = move(obj1); // move constructor !empty
1032 BOOST_CHECK(obj3);
1033 BOOST_CHECK(!obj1);
1034
1035 Src obj4; obj4 = move(obj2); // move assignment !empty -> empty
1036 BOOST_CHECK(obj4);
1037 BOOST_CHECK(!obj2);
1038
1039 // different types
1040 Dst obj5 = obj3; // copy constructor !empty
1041 BOOST_CHECK(obj5);
1042 BOOST_CHECK(obj5 == obj3);
1043
1044 Dst obj6; obj6 = obj4; // assignment !empty -> empty
1045 BOOST_CHECK(obj6);
1046 BOOST_CHECK(!(obj6 != obj4));
1047
1048 Dst obj7 = move(obj3); // move constructor !empty
1049 BOOST_CHECK(obj7);
1050 BOOST_CHECK(!obj3);
1051
1052 Dst obj8; obj8 = move(obj4); // move assignment !empty -> empty
1053 BOOST_CHECK(obj8);
1054 BOOST_CHECK(!obj4);
1055
1056 obj6 = obj5; // assignment !empty -> !empty
1057 BOOST_CHECK(obj5);
1058 BOOST_CHECK(obj6);
1059
1060 obj6 = move(obj5); // move assignment !empty -> !empty
1061 BOOST_CHECK(!obj5);
1062 BOOST_CHECK(obj6);
1063
1064 obj6 = obj3; // assignment empty -> !empty
1065 BOOST_CHECK(!obj6);
1066
1067 obj8 = obj7; // assignment !empty -> !empty
1068 BOOST_CHECK(obj7);
1069 BOOST_CHECK(obj8);
1070
1071 obj8 = move(obj7); // move assignment !empty -> !empty
1072 BOOST_CHECK(!obj7);
1073 BOOST_CHECK(obj8);
1074
1075 obj8 = move(Src()); // move assignment empty -> !empty
1076 BOOST_CHECK(!obj8);
1077
1078 BOOST_REQUIRE(obj0);
1079 BOOST_REQUIRE(dynamic_cast<const CObject*>(obj0.GetPointerOrNull()));
1080 BOOST_CHECK(dynamic_cast<const CObject*>(obj0.GetPointerOrNull())->ReferencedOnlyOnce());
1081 }
1082
1083
1084 struct ITestMoveInt1
1085 {
ITestMoveInt1ITestMoveInt11086 ITestMoveInt1() {}
~ITestMoveInt1ITestMoveInt11087 virtual ~ITestMoveInt1() {}
1088
1089 ITestMoveInt1(const ITestMoveInt1&) = delete;
1090 ITestMoveInt1(ITestMoveInt1&&) = delete;
1091 void operator=(const ITestMoveInt1&) = delete;
1092 void operator=(ITestMoveInt1&&) = delete;
1093
1094 virtual void foo() = 0;
1095 };
1096 struct ITestMoveInt2 : public ITestMoveInt1
1097 {
~ITestMoveInt2ITestMoveInt21098 virtual ~ITestMoveInt2() override {}
1099
1100 virtual void bar() = 0;
1101 };
1102
1103 struct CTestMoveInt1 : public CObject, public ITestMoveInt1
1104 {
1105 static int counter;
CTestMoveInt1CTestMoveInt11106 CTestMoveInt1() { ++counter; }
~CTestMoveInt1CTestMoveInt11107 virtual ~CTestMoveInt1() { --counter; }
1108
fooCTestMoveInt11109 virtual void foo() override {}
1110 };
1111 int CTestMoveInt1::counter;
1112 struct CTestMoveInt2 : public CObject, public ITestMoveInt2
1113 {
1114 static int counter;
CTestMoveInt2CTestMoveInt21115 CTestMoveInt2() { ++counter; }
~CTestMoveInt2CTestMoveInt21116 virtual ~CTestMoveInt2() { --counter; }
1117
fooCTestMoveInt21118 virtual void foo() override {}
barCTestMoveInt21119 virtual void bar() override {}
1120 };
1121 int CTestMoveInt2::counter;
1122
BOOST_AUTO_TEST_CASE(TestCRefMove)1123 BOOST_AUTO_TEST_CASE(TestCRefMove)
1124 {
1125 if ( 1 ) {
1126 s_TestCopyMove<CRef<CTestMoveInt1>, CRef<CTestMoveInt1>>();
1127 s_TestCopyMove<CRef<CTestMoveInt1>, CConstRef<CTestMoveInt1>>();
1128 s_TestCopyMove<CConstRef<CTestMoveInt1>, CConstRef<CTestMoveInt1>>();
1129 s_TestCopyMove<CRef<CTestMoveInt1>, CRef<CObject>>();
1130 s_TestCopyMove<CRef<CTestMoveInt1>, CConstRef<CObject>>();
1131 s_TestCopyMove<CConstRef<CTestMoveInt1>, CConstRef<CObject>>();
1132 }
1133
1134 if ( 1 ) {
1135 s_TestCopyMove<CIRef<ITestMoveInt2>, CIRef<ITestMoveInt2>, CTestMoveInt2, CTestMoveInt2>();
1136 s_TestCopyMove<CIRef<ITestMoveInt2>, CConstIRef<ITestMoveInt2>, CTestMoveInt2, CTestMoveInt2>();
1137 s_TestCopyMove<CConstIRef<ITestMoveInt2>, CConstIRef<ITestMoveInt2>, CTestMoveInt2, CTestMoveInt2>();
1138 s_TestCopyMove<CIRef<ITestMoveInt2>, CIRef<ITestMoveInt1>, CTestMoveInt2, CTestMoveInt1>();
1139 s_TestCopyMove<CIRef<ITestMoveInt2>, CConstIRef<ITestMoveInt1>, CTestMoveInt2, CTestMoveInt1>();
1140 s_TestCopyMove<CConstIRef<ITestMoveInt2>, CConstIRef<ITestMoveInt1>, CTestMoveInt2, CTestMoveInt1>();
1141 }
1142 BOOST_CHECK_EQUAL(CTestMoveInt1::counter, 0);
1143 BOOST_CHECK_EQUAL(CTestMoveInt2::counter, 0);
1144
1145 // these should not compile
1146 //CRef<CObjectFor<int>> t1 = obj4;
1147 //CRef<CObjectFor<int>> t2; t2 = obj4;
1148 //CRef<CObjectFor<int>> t3 = std::move(obj4);
1149 //CRef<CObjectFor<int>> t4; t4 = std::move(obj4);
1150 }
1151
1152
1153 /////////////////////////////////////////////////////////////////////////////
1154
BOOST_AUTO_TEST_CASE(TestBASE64Encoding)1155 BOOST_AUTO_TEST_CASE(TestBASE64Encoding)
1156 {
1157 const char test_string[] = "Quick brown fox jumps over the lazy dog";
1158 char buf1[1024], buf2[1024], buf3[1024];
1159 size_t read, written, len = 16, i, j;
1160
1161 BASE64_Encode(test_string, strlen(test_string) + 1, &read,
1162 buf1, sizeof(buf1), &written, &len);
1163 BOOST_CHECK(read == strlen(test_string) + 1);
1164 BOOST_CHECK(written < sizeof(buf1));
1165 BOOST_CHECK(buf1[written] == '\0');
1166
1167 BOOST_CHECK(BASE64_Decode(buf1, written, &read,
1168 buf2, sizeof(buf2), &written));
1169 BOOST_CHECK(strlen(buf1) == read);
1170 BOOST_CHECK(written == strlen(test_string) + 1);
1171 BOOST_CHECK(buf2[written - 1] == '\0');
1172 BOOST_CHECK(strcmp(buf2, test_string) == 0);
1173
1174 for (i = 0; i < 100; i++) {
1175 len = rand() % 250;
1176 memset(buf1, '\0', sizeof(buf1));
1177 memset(buf2, '\0', sizeof(buf2));
1178 memset(buf3, '\0', sizeof(buf3));
1179 for (j = 0; j < len; j++) {
1180 buf1[j] = char(rand() & 0xFF);
1181 }
1182
1183 j = rand() % 100;
1184 BASE64_Encode(buf1, len, &read, buf2, sizeof(buf2), &written, &j);
1185 if (len != read)
1186 NcbiCerr << "len = " << len << ", read = " << read << NcbiEndl;
1187 BOOST_CHECK(len == read);
1188 BOOST_CHECK(written < sizeof(buf2));
1189 BOOST_CHECK(buf2[written] == '\0');
1190
1191 if (rand() & 1) {
1192 buf2[written] = '=';
1193 }
1194 j = written;
1195 BASE64_Decode(buf2, j, &read, buf3, sizeof(buf3), &written);
1196 if (j != read)
1197 NcbiCerr << "j = " << len << ", read = " << read << NcbiEndl;
1198 BOOST_CHECK(j == read);
1199 BOOST_CHECK(len == written);
1200 BOOST_CHECK(memcmp(buf1, buf3, len) == 0);
1201 }
1202 }
1203
1204
1205 /////////////////////////////////////////////////////////////////////////////
1206
1207 class CCharVector
1208 {
1209 public:
CCharVector(const char * str)1210 CCharVector(const char* str)
1211 : m_begin(str),
1212 m_end(str+strlen(str))
1213 {
1214 }
1215
1216 typedef char value_type;
1217 typedef char* pointer;
1218 typedef char& reference;
1219 typedef const char* const_pointer;
1220 typedef const char& const_reference;
1221
1222 typedef char* iterator;
1223 typedef const char* const_iterator;
1224
1225 struct const_reverse_iterator {
const_reverse_iteratorCCharVector::const_reverse_iterator1226 const_reverse_iterator(const char* p)
1227 : ptr(p)
1228 {
1229 }
1230
operator ==CCharVector::const_reverse_iterator1231 bool operator==(const_reverse_iterator rhs) const
1232 { return ptr == rhs.ptr; }
operator !=CCharVector::const_reverse_iterator1233 bool operator!=(const_reverse_iterator rhs) const
1234 { return ptr != rhs.ptr; }
operator ++CCharVector::const_reverse_iterator1235 const_reverse_iterator& operator++()
1236 { --ptr; return *this; }
operator --CCharVector::const_reverse_iterator1237 const_reverse_iterator& operator--()
1238 { ++ptr; return *this; }
1239
operator *CCharVector::const_reverse_iterator1240 char operator*() const { return ptr[-1]; }
1241
1242 private:
1243 const char* ptr;
1244 };
1245
1246
begin() const1247 const_iterator begin() const
1248 {
1249 return m_begin;
1250 }
end() const1251 const_iterator end() const
1252 {
1253 return m_end;
1254 }
1255
rbegin() const1256 const_reverse_iterator rbegin() const
1257 {
1258 return const_reverse_iterator(m_end);
1259 }
rend() const1260 const_reverse_iterator rend() const
1261 {
1262 return const_reverse_iterator(m_begin);
1263 }
1264
begin()1265 iterator begin()
1266 {
1267 throw runtime_error("non-const begin called");
1268 }
end()1269 iterator end()
1270 {
1271 throw runtime_error("non-const end called");
1272 }
1273
rbegin()1274 iterator rbegin()
1275 {
1276 throw runtime_error("non-const rbegin called");
1277 }
rend()1278 iterator rend()
1279 {
1280 throw runtime_error("non-const rend called");
1281 }
1282
1283 private:
1284 const char* m_begin;
1285 const char* m_end;
1286 };
1287
1288 template<class C>
TestIterateFor(const C &)1289 void TestIterateFor(const C&)
1290 {
1291 typedef C Cont;
1292 for ( int t = 0; t < 100; ++t ) {
1293 Cont c;
1294 for ( int i = 0; i < 100; ++i ) {
1295 c.insert(c.end(), rand());
1296 }
1297 vector<int> pc1, pc2;
1298 ITERATE ( typename Cont, it, c ) {
1299 pc1.push_back(*it);
1300 }
1301 NON_CONST_ITERATE ( typename Cont, it, c ) {
1302 *it += 1;
1303 }
1304 ITERATE ( typename Cont, it, c ) {
1305 pc2.push_back(*it);
1306 }
1307 NON_CONST_ITERATE ( vector<int>, it, pc1 ) {
1308 *it += 1;
1309 }
1310 vector<int> pc3, pc4;
1311 REVERSE_ITERATE ( typename Cont, it, c ) {
1312 pc3.push_back(*it);
1313 }
1314 NON_CONST_REVERSE_ITERATE ( typename Cont, it, c ) {
1315 *it -= 1;
1316 }
1317 REVERSE_ITERATE ( typename Cont, it, c ) {
1318 pc4.push_back(*it);
1319 }
1320 NON_CONST_ITERATE ( vector<int>, it, pc4 ) {
1321 *it += 1;
1322 }
1323 reverse(pc3.begin(), pc3.end());
1324 reverse(pc4.begin(), pc4.end());
1325
1326 BOOST_CHECK(pc1 == pc2);
1327 BOOST_CHECK(pc3 == pc4);
1328 BOOST_CHECK(pc1 == pc3);
1329 }
1330 }
1331
1332
1333 template<class C>
TestCIterate(C & c)1334 void TestCIterate(C& c)
1335 {
1336 typedef C Cont;
1337 vector<int> pc1, pc2;
1338 ITERATE ( typename Cont, it, c ) {
1339 pc1.push_back(*it);
1340 }
1341 REVERSE_ITERATE ( typename Cont, it, c ) {
1342 pc2.push_back(*it);
1343 }
1344 reverse(pc2.begin(), pc2.end());
1345 BOOST_CHECK(pc1 == pc2);
1346 }
1347
1348
1349 template<class C>
TestCIterateFor(const C &)1350 void TestCIterateFor(const C&)
1351 {
1352 typedef C Cont;
1353 for ( int t = 0; t < 100; ++t ) {
1354 Cont c;
1355 for ( int i = 0; i < 100; ++i ) {
1356 c.insert(c.end(), rand());
1357 }
1358 TestCIterate(c);
1359 }
1360 }
1361
1362
1363 template<class C>
TestEraseIterateFor(const C &)1364 void TestEraseIterateFor(const C&)
1365 {
1366 typedef C Cont;
1367 for ( int t = 0; t < 100; ++t ) {
1368 Cont c;
1369 for ( int i = 0; i < 100; ++i ) {
1370 c.insert(c.end(), rand());
1371 }
1372 while ( !c.empty() ) {
1373 vector<int> pc;
1374 ITERATE ( typename Cont, it, c ) {
1375 pc.push_back(*it);
1376 }
1377 size_t p = rand()%pc.size();
1378 int v = pc[p];
1379 vector<int> nc;
1380 ERASE_ITERATE ( typename Cont, it, c ) {
1381 if ( *it == v ) {
1382 c.erase(it);
1383 }
1384 else {
1385 nc.push_back(*it);
1386 }
1387 }
1388 pc.erase(remove(pc.begin(), pc.end(), v), pc.end());
1389 BOOST_CHECK(pc == nc);
1390 nc.clear();
1391 ITERATE ( typename Cont, it, c ) {
1392 nc.push_back(*it);
1393 }
1394 BOOST_CHECK(pc == nc);
1395 }
1396 }
1397 }
1398
1399
1400 template<class C>
TestEraseIterateForVec(const C &)1401 void TestEraseIterateForVec(const C&)
1402 {
1403 typedef C Cont;
1404 for ( int t = 0; t < 100; ++t ) {
1405 Cont c;
1406 for ( int i = 0; i < 100; ++i ) {
1407 c.insert(c.end(), rand());
1408 }
1409 while ( !c.empty() ) {
1410 vector<int> pc;
1411 ITERATE ( typename Cont, it, c ) {
1412 pc.push_back(*it);
1413 }
1414 size_t p = rand()%pc.size();
1415 int v = pc[p];
1416 vector<int> nc;
1417 ERASE_ITERATE ( typename Cont, it, c ) {
1418 if ( *it == v ) {
1419 VECTOR_ERASE(it, c);
1420 }
1421 else {
1422 nc.push_back(*it);
1423 }
1424 }
1425 pc.erase(remove(pc.begin(), pc.end(), v), pc.end());
1426 BOOST_CHECK(pc == nc);
1427 nc.clear();
1428 ITERATE ( typename Cont, it, c ) {
1429 nc.push_back(*it);
1430 }
1431 BOOST_CHECK(pc == nc);
1432 }
1433 }
1434 }
1435
1436
BOOST_AUTO_TEST_CASE(TestIterate)1437 BOOST_AUTO_TEST_CASE(TestIterate)
1438 {
1439 CCharVector cv("test");
1440 set<int> ts;
1441 list<int> tl;
1442 vector<int> tv;
1443 TestCIterate(cv);
1444 TestCIterateFor(ts);
1445 TestIterateFor(tl);
1446 TestIterateFor(tv);
1447 }
1448
1449
BOOST_AUTO_TEST_CASE(TestEraseIterate)1450 BOOST_AUTO_TEST_CASE(TestEraseIterate)
1451 {
1452 set<int> ts;
1453 list<int> tl;
1454 vector<int> tv;
1455 TestEraseIterateFor(ts);
1456 TestEraseIterateFor(tl);
1457 TestEraseIterateForVec(tv);
1458 }
1459
1460
1461 /////////////////////////////////////////////////////////////////////////////
1462
BOOST_AUTO_TEST_CASE(TestStringNpos)1463 BOOST_AUTO_TEST_CASE(TestStringNpos)
1464 {
1465 BOOST_CHECK(string::npos == static_cast<string::size_type>(-1));
1466 BOOST_CHECK(NPOS == static_cast<SIZE_TYPE>(-1));
1467 }
1468
1469 /////////////////////////////////////////////////////////////////////////////
1470
1471
chk1_True(void)1472 CCheckMe<bool> chk1_True(void)
1473 {
1474 return true;
1475 }
chk1_False(void)1476 CCheckMe<bool> chk1_False(void)
1477 {
1478 return CCheckMe<bool>(false);
1479 }
chk2_False(void)1480 CCheckMe<bool> chk2_False(void)
1481 {
1482 CCheckMe<bool> f(chk1_False());
1483 return f;
1484 }
chk3_False(void)1485 CCheckMe<bool> chk3_False(void)
1486 {
1487 CCheckMe<bool> f(chk1_False());
1488 return CCheckMe<bool>(f);
1489 }
1490
1491 class TwoInt
1492 {
1493 public:
TwoInt(int lo,int hi)1494 TwoInt(int lo, int hi)
1495 : m_Lo(lo), m_Hi(hi)
1496 {
1497 }
TwoInt(const TwoInt & t)1498 TwoInt(const TwoInt& t)
1499 : m_Lo(t.m_Lo), m_Hi(t.m_Hi)
1500 {
1501 }
operator ==(const int & lo) const1502 bool operator==(const int& lo) const
1503 {
1504 return m_Lo == lo && m_Hi == 0;
1505 }
1506 private:
1507 int m_Lo, m_Hi;
1508 };
1509
BOOST_AUTO_TEST_CASE(TestCheckMeType)1510 BOOST_AUTO_TEST_CASE(TestCheckMeType)
1511 {
1512 {
1513 CCheckMe<bool> b(false);
1514 BOOST_CHECK(!b.IsChecked());
1515 bool v = b;
1516 BOOST_CHECK(!v);
1517 BOOST_CHECK(b.IsChecked());
1518 }
1519 {
1520 CCheckMe<bool> b(false);
1521 BOOST_CHECK(!b.IsChecked());
1522 bool v = !b;
1523 BOOST_CHECK(v);
1524 BOOST_CHECK(b.IsChecked());
1525 }
1526 {
1527 CCheckMe<bool> b(false);
1528 BOOST_CHECK(!b.IsChecked());
1529 bool v = (b == false);
1530 BOOST_CHECK(v);
1531 BOOST_CHECK(b.IsChecked());
1532 }
1533 {
1534 CCheckMe<bool> b(false);
1535 BOOST_CHECK(!b.IsChecked());
1536 bool v = (b != false);
1537 BOOST_CHECK(!v);
1538 BOOST_CHECK(b.IsChecked());
1539 }
1540
1541 {
1542 CCheckMe<bool> b(false);
1543 BOOST_CHECK(!b.IsChecked());
1544
1545 CCheckMe<bool> x = b;
1546 BOOST_CHECK(b.IsChecked());
1547 BOOST_CHECK(!x.IsChecked());
1548
1549 CCheckMe<bool> y(false);
1550 BOOST_CHECK(!y.IsChecked());
1551 bool v = x == y;
1552 BOOST_CHECK(v);
1553 BOOST_CHECK(x.IsChecked());
1554 BOOST_CHECK(y.IsChecked());
1555
1556 y = false;
1557 BOOST_CHECK(!y.IsChecked());
1558 y.SetChecked();
1559 }
1560 {
1561 CCheckMe<bool> x(true);
1562 BOOST_CHECK(!x.IsChecked());
1563 CCheckMe<bool> y(false);
1564 BOOST_CHECK(!y.IsChecked());
1565 bool v = x != y;
1566 BOOST_CHECK(v);
1567 BOOST_CHECK(x.IsChecked());
1568 BOOST_CHECK(y.IsChecked());
1569 }
1570 {
1571 // test that it does not crash here
1572 bool v = chk1_True();
1573 BOOST_CHECK(v);
1574 v = !chk1_True();
1575 BOOST_CHECK(!v);
1576 v = chk1_False();
1577 BOOST_CHECK(!v);
1578 v = !chk1_False();
1579 BOOST_CHECK(v);
1580 v = chk2_False();
1581 BOOST_CHECK(!v);
1582 v = !chk2_False();
1583 BOOST_CHECK(v);
1584 v = chk3_False();
1585 BOOST_CHECK(!v);
1586 v = !chk3_False();
1587 BOOST_CHECK(v);
1588 }
1589 {
1590 CCheckMe<bool> x = chk1_True();
1591 BOOST_CHECK(!x.IsChecked());
1592 x.SetChecked();
1593
1594 x = chk1_False();
1595 BOOST_CHECK(!x.IsChecked());
1596 x.SetChecked();
1597
1598 x = chk2_False();
1599 BOOST_CHECK(!x.IsChecked());
1600 x.SetChecked();
1601
1602 x = chk3_False();
1603 BOOST_CHECK(!x.IsChecked());
1604 x.SetChecked();
1605 }
1606 {
1607 CCheckMe<bool> b;
1608 BOOST_CHECK(b.IsChecked());
1609
1610 CCheckMe<bool> z;
1611 BOOST_CHECK(z.IsChecked());
1612 z = b;
1613 BOOST_CHECK(b.IsChecked());
1614 BOOST_CHECK(z.IsChecked());
1615
1616 CCheckMe<bool> x = b;
1617 BOOST_CHECK(b.IsChecked());
1618 BOOST_CHECK(x.IsChecked());
1619 x = true;
1620 BOOST_CHECK(!x.IsChecked());
1621
1622 CCheckMe<bool> y(false);
1623 BOOST_CHECK(!y.IsChecked());
1624 bool v = x == y;
1625 BOOST_CHECK(!v);
1626 BOOST_CHECK(x.IsChecked());
1627 BOOST_CHECK(y.IsChecked());
1628 }
1629 {
1630 CCheckMe<TwoInt> x(TwoInt(3,0));
1631 BOOST_CHECK(!x.IsChecked());
1632 bool v = x == 3;
1633 BOOST_CHECK(v);
1634 BOOST_CHECK(x.IsChecked());
1635 }
1636 }
1637
1638 /////////////////////////////////////////////////////////////////////////////
1639
BOOST_AUTO_TEST_CASE(TestAutoEnv)1640 BOOST_AUTO_TEST_CASE(TestAutoEnv)
1641 {
1642 CNcbiEnvironment& env = CNcbiApplication::Instance()->SetEnvironment();
1643 vector<string> options;
1644 options.push_back("unset");
1645 options.push_back("empty");
1646 options.push_back("nonempty");
1647
1648 string name;
1649 bool found;
1650
1651 ITERATE (vector<string>, it, options) {
1652 env.Unset(name = ("unset_" + *it));
1653 BOOST_CHECK(env.Get(name, &found).empty() && !found);
1654 env.Set(name = ("empty_" + *it), kEmptyStr);
1655 BOOST_CHECK(env.Get(name, &found).empty() && found);
1656 env.Set(name = ("nonempty_" + *it), "foo");
1657 BOOST_CHECK(env.Get(name, &found) == "foo" && found);
1658 }
1659
1660 ITERATE (vector<string>, it, options) {
1661 CAutoEnvironmentVariable temp_unset(name = (*it + "_unset"),
1662 kEmptyStr, &env);
1663 BOOST_CHECK(env.Get(name, &found).empty() && !found);
1664 CAutoEnvironmentVariable temp_empty(name = (*it + "_empty"),
1665 kEmptyStr, &env);
1666 env.Set(name, kEmptyStr);
1667 BOOST_CHECK(env.Get(name, &found).empty() && found);
1668 CAutoEnvironmentVariable temp_nonempty(name = (*it + "_nonempty"),
1669 "bar", &env);
1670 BOOST_CHECK(env.Get(name, &found) == "bar" && found);
1671 }
1672
1673 ITERATE (vector<string>, it, options) {
1674 BOOST_CHECK(env.Get("unset_" + *it, &found).empty() && !found);
1675 BOOST_CHECK(env.Get("empty_" + *it, &found).empty() && found);
1676 BOOST_CHECK(env.Get("nonempty_" + *it, &found) == "foo" && found);
1677 }
1678 }
1679
1680 /////////////////////////////////////////////////////////////////////////////
1681 // CHECK std::hash SPECIALIZATION FOR CStringGi
1682 /////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(TestHashTGi)1683 BOOST_AUTO_TEST_CASE(TestHashTGi)
1684 {
1685 NcbiCerr << "Test unordered_map<TGi>:" << NcbiEndl;
1686 unordered_map<TGi, string> my_map;
1687 my_map[TGi((TIntId)566)] = "Hi!";
1688 my_map[TGi((TIntId)2523432)] = "Connitchiva!";
1689 my_map[TGi((TIntId)153)] = "Hallo!";
1690 my_map[TGi((TIntId)1345134)] = "Hello!";
1691 my_map[TGi((TIntId)13245)] = "Guten Tag!";
1692 my_map[TGi((TIntId)2745)] = "Privet!";
1693
1694 map<string, bool> test_items;
1695 test_items["Hi!"] = false;
1696 test_items["Connitchiva!"] = false;
1697 test_items["Hallo!"] = false;
1698 test_items["Hello!"] = false;
1699 test_items["Guten Tag!"] = false;
1700 test_items["Privet!"] = false;
1701
1702 // Loop should hit every item in test_items
1703 for (auto a : my_map) {
1704 test_items[a.second] = true;
1705 }
1706
1707 // Test that all elements in test_items were hit and no additional
1708 // items were added
1709 NCBITEST_CHECK_EQUAL(test_items.size(), 6U);
1710 NCBITEST_CHECK_EQUAL(test_items["Hi!"], true);
1711 NCBITEST_CHECK_EQUAL(test_items["Connitchiva!"], true);
1712 NCBITEST_CHECK_EQUAL(test_items["Hallo!"], true);
1713 NCBITEST_CHECK_EQUAL(test_items["Hello!"], true);
1714 NCBITEST_CHECK_EQUAL(test_items["Guten Tag!"], true);
1715 NCBITEST_CHECK_EQUAL(test_items["Privet!"], true);
1716
1717 // Test random access
1718 NCBITEST_CHECK_EQUAL(my_map[TGi((TIntId)566)], "Hi!");
1719 NCBITEST_CHECK_EQUAL(my_map[TGi((TIntId)2523432)], "Connitchiva!");
1720 NCBITEST_CHECK_EQUAL(my_map[TGi((TIntId)153)], "Hallo!");
1721 NCBITEST_CHECK_EQUAL(my_map[TGi((TIntId)1345134)], "Hello!");
1722 NCBITEST_CHECK_EQUAL(my_map[TGi((TIntId)13245)], "Guten Tag!");
1723 NCBITEST_CHECK_EQUAL(my_map[TGi((TIntId)2745)], "Privet!");
1724 }
1725
NCBITEST_AUTO_INIT()1726 NCBITEST_AUTO_INIT()
1727 {
1728 // Post error message
1729 ERR_POST("This message goes to the default diag.stream, CERR (2 times)");
1730 }
1731
NCBITEST_AUTO_FINI()1732 NCBITEST_AUTO_FINI()
1733 {
1734 SetDiagStream(0);
1735 assert( IsDiagStream(0) );
1736 assert( !IsDiagStream(&NcbiCout) );
1737 }
1738