1 /* $Id: test_ncbiexpt.cpp 620642 2020-11-25 17:54:32Z lavr $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Authors: Andrei Gourianov,
27 *
28 * File Description: Test CNcbiException and based classes
29 *
30 */
31
32 #include <ncbi_pch.hpp>
33 #include <corelib/ncbistd.hpp>
34 #include <corelib/ncbiapp.hpp>
35 #include <corelib/ncbienv.hpp>
36 #include <corelib/ncbiargs.hpp>
37 #include <corelib/ncbithr.hpp>
38 #include <errno.h>
39
40 #include <common/test_assert.h> /* This header must go last */
41
42
43 BEGIN_NCBI_SCOPE
44
45 /////////////////////////////////////////////////////////////////////////////
46 // CExceptionSubsystem
47
48 #if defined(EXCEPTION_BUG_WORKAROUND)
49 class CSubsystemException : public CException
50 #else
51 class CSubsystemException : virtual public CException
52 #endif
53 {
54 public:
55 enum EErrCode {
56 eType1,
57 eType2
58 };
GetErrCodeString(void) const59 virtual const char* GetErrCodeString(void) const
60 {
61 switch (GetErrCode()) {
62 case eType1: return "eType1";
63 case eType2: return "eType2";
64 default: return CException::GetErrCodeString();
65 }
66 }
67 NCBI_EXCEPTION_DEFAULT(CSubsystemException,CException);
68 };
69
70 /////////////////////////////////////////////////////////////////////////////
71 // CSupersystemException
72
73 class CSupersystemException : public CSubsystemException
74 {
75 public:
76 enum EErrCode {
77 eSuper1,
78 eSuper2
79 };
GetErrCodeString(void) const80 virtual const char* GetErrCodeString(void) const
81 {
82 switch (GetErrCode()) {
83 case eSuper1: return "eSuper1";
84 case eSuper2: return "eSuper2";
85 default: return CException::GetErrCodeString();
86 }
87 }
88 NCBI_EXCEPTION_DEFAULT(CSupersystemException, CSubsystemException);
89 };
90
91 /////////////////////////////////////////////////////////////////////////////
92 // CIncompletelyImplementedException
93
94 class CIncompletelyImplementedException : public CSupersystemException
95 {
96 public:
CIncompletelyImplementedException(const CSupersystemException & e)97 CIncompletelyImplementedException(const CSupersystemException& e)
98 : CSupersystemException(e)
99 { }
100 };
101
102
103 class CErrnoMoreException : public CErrnoTemplException<CCoreException>
104 {
105 public:
106 enum EErrCode {
107 eMore1,
108 eMore2
109 };
GetErrCodeString(void) const110 virtual const char* GetErrCodeString(void) const
111 {
112 switch (GetErrCode()) {
113 case eMore1: return "eMore1";
114 case eMore2: return "eMore2";
115 default: return CException::GetErrCodeString();
116 }
117 }
118 NCBI_EXCEPTION_DEFAULT(CErrnoMoreException,CErrnoTemplException<CCoreException>);
119 };
120
121 /////////////////////////////////////////////////////////////////////////////
122 // CExceptApplication::
123
124 class CExceptApplication : public CNcbiApplication
125 {
126 private:
127 void f1(void);
128 void f2(void);
129 void f3(void);
130 void f4(void);
131
132 void s1(void);
133 void s2(void);
134
135 void t1(void);
136 void m1(void);
137
138 void tp1(void);
139 private:
140 virtual int Run(void);
141 };
142
143 //---------------------------------------------------------------------------
f1(void)144 void CExceptApplication::f1(void)
145 {
146 try {
147 f2();
148 }
149 catch (CException& e) { // catch by reference
150 // verify error code
151 assert(e.GetErrCode() == CException::eInvalid);
152 // verify exception class
153 assert(!UppermostCast<CException>(e));
154 assert(UppermostCast<CSubsystemException>(e));
155 assert(!UppermostCast<CSupersystemException>(e));
156 // verify error code
157 const CSubsystemException *pe = UppermostCast<CSubsystemException>(e);
158 assert(pe->GetErrCode() == CSubsystemException::eType2);
159
160 NCBI_RETHROW_SAME(e,"calling f2 from f1");
161 }
162 }
163
f2(void)164 void CExceptApplication::f2(void)
165 {
166 try {
167 f3();
168 }
169 catch (CSubsystemException e) { /* NCBI_FAKE_WARNING */ // catch by value
170 /*
171 catching exception by value results in copying
172 CSupersystemException into CSubsystemException and
173 loosing all meaning of the "original" exception
174 i.e. only location and message info is preserved
175 while err.code becomes invalid
176 */
177 // verify error code
178 assert((int)e.GetErrCode() == (int)CException::eInvalid);
179
180 NCBI_RETHROW(e,CSubsystemException,eType2,"calling f3 from f2");
181 }
182 }
183
f3(void)184 void CExceptApplication::f3(void)
185 {
186 try {
187 f4();
188 }
189 catch (CSubsystemException& e) { // catch by reference
190 // verify error code
191 assert((int)(e.GetErrCode()) == (int)CException::eInvalid);
192 // verify exception class
193 assert(!UppermostCast<CException>(e));
194 assert(!UppermostCast<CSubsystemException>(e));
195 assert(UppermostCast<CSupersystemException>(e));
196 // verify error code
197 const CSupersystemException *pe = UppermostCast<CSupersystemException>(e);
198 assert(pe->GetErrCode() == CSupersystemException::eSuper2);
199
200 // error code string is always correct
201 assert( strcmp(e.GetErrCodeString(),
202 pe->GetErrCodeString())==0);
203
204 // NCBI_RETHROW_SAME(e,"calling f4 from f3");
205 e.AddBacklog(DIAG_COMPILE_INFO, "calling f4 from f3", e.GetSeverity());
206 e.Throw();
207 }
208 }
209
f4(void)210 void CExceptApplication::f4(void)
211 {
212 // NCBI_THROW(CSupersystemException,eSuper2,"from f4");
213
214 NCBI_EXCEPTION_VAR(f4_ex, CSupersystemException, eSuper2, "from f4");
215 f4_ex.SetSeverity(eDiag_Critical);
216 try {
217 CIncompletelyImplementedException f4_ex2(f4_ex);
218 f4_ex2.Throw(); // slices (and warns about doing so)
219 } catch (CSupersystemException& e) {
220 assert(UppermostCast<CSupersystemException>(e));
221 // ErrCode trashed, though it would have been safe to keep in
222 // this case.
223 assert((int)e.GetErrCode() == (int)CException::eInvalid);
224 } catch (...) {
225 assert(0);
226 }
227 NCBI_EXCEPTION_THROW(f4_ex);
228
229 // throw CSupersystemException(DIAG_COMPILE_INFO, 0, CSupersystemException::eSuper2, "from f4", eDiag_Warning);
230 }
231
t1(void)232 void CExceptApplication::t1(void)
233 {
234 NCBI_THROW(CErrnoTemplException<CCoreException>,eErrno,"from t1");
235 }
236
m1(void)237 void CExceptApplication::m1(void)
238 {
239 NCBI_THROW(CErrnoMoreException,eMore2,"from m1");
240 }
241
tp1(void)242 void CExceptApplication::tp1(void)
243 {
244 NCBI_THROW2(CParseTemplException<CCoreException>,eErr,"from tp1",123);
245 }
246
247 //---------------------------------------------------------------------------
248
Run(void)249 int CExceptApplication::Run(void)
250 {
251
252 try {
253 f1();
254 }
255 catch (CException& e) {
256
257 // Attributes
258 // verify error code
259 assert(e.GetErrCode() == CException::eInvalid);
260 // verify exception class
261 assert(!UppermostCast<CException>(e));
262 assert(UppermostCast<CSubsystemException>(e));
263 assert(!UppermostCast<CSupersystemException>(e));
264 // verify error code
265 assert(UppermostCast<CSubsystemException>(e)->GetErrCode() ==
266 CSubsystemException::eType2);
267
268
269 // verify predecessors
270 const CException* pred;
271
272
273 pred = e.GetPredecessor();
274 assert(pred);
275 assert(pred->GetErrCode() == CException::eInvalid);
276 // verify exception class
277 assert(!UppermostCast<CException>(*pred));
278 assert(UppermostCast<CSubsystemException>(*pred));
279 assert(!UppermostCast<CSupersystemException>(*pred));
280 // verify error code
281 assert(UppermostCast<CSubsystemException>(*pred)->GetErrCode() ==
282 CSubsystemException::eType2);
283
284
285 pred = pred->GetPredecessor();
286 assert(pred);
287 assert(pred->GetErrCode() == CException::eInvalid);
288 // verify exception class
289 assert(!UppermostCast<CException>(*pred));
290 assert(UppermostCast<CSubsystemException>(*pred));
291 assert(!UppermostCast<CSupersystemException>(*pred));
292 // verify error code
293 assert((int)UppermostCast<CSubsystemException>(*pred)->GetErrCode() ==
294 (int)CException::eInvalid);
295
296
297 pred = pred->GetPredecessor();
298 assert(pred);
299 assert(pred->GetErrCode() == CException::eInvalid);
300 // verify exception class
301 assert(!UppermostCast<CException>(*pred));
302 assert(!UppermostCast<CSubsystemException>(*pred));
303 assert(UppermostCast<CSupersystemException>(*pred));
304 // verify error code
305 assert(UppermostCast<CSupersystemException>(*pred)->GetErrCode() ==
306 CSupersystemException::eSuper2);
307
308
309
310 // Reporting
311 cerr << endl;
312 ERR_POST("****** ERR_POST ******" << e << "err_post ends");
313
314 cerr << endl << "****** e.ReportAll() ******" << endl;
315 cerr << e.ReportAll();
316
317 cerr << endl << "****** e.what() ******" << endl;
318 cerr << e.what();
319
320 cerr << endl << "****** e.ReportThis() ******" << endl;
321 cerr << e.ReportThis() << endl;
322
323 CExceptionReporterStream reporter(cerr);
324 CExceptionReporter::SetDefault(&reporter);
325 CExceptionReporter::EnableDefault(false);
326
327 cerr << endl;
328 e.Report(DIAG_COMPILE_INFO,
329 "****** stream reporter ******", &reporter, eDPF_All);
330 cerr << endl;
331 NCBI_REPORT_EXCEPTION(
332 "****** default reporter (stream, disabled) ******",e);
333
334 CExceptionReporter::EnableDefault(true);
335 cerr << endl;
336 NCBI_REPORT_EXCEPTION(
337 "****** default reporter (stream) ******",e);
338
339 CExceptionReporter::SetDefault(0);
340 cerr << endl;
341 NCBI_REPORT_EXCEPTION(
342 "****** default reporter (diag) ******",e);
343 }
344 catch (exception& /*e*/) {
345 assert(0);
346 }
347
348
349 try {
350 t1();
351 } catch (CErrnoTemplException<CCoreException>& e) {
352 NCBI_REPORT_EXCEPTION("caught as CErrnoTemplException<CCoreException>", e);
353 assert(e.GetErrCode() == CErrnoTemplException<CCoreException>::eErrno);
354 } catch (CCoreException& e) {
355 NCBI_REPORT_EXCEPTION("caught as CCoreException", e);
356 const CErrnoTemplException<CCoreException>* pe = UppermostCast< CErrnoTemplException<CCoreException> > (e);
357 assert(pe->GetErrCode() == CErrnoTemplException<CCoreException>::eErrno);
358 } catch (exception&) {
359 assert(0);
360 }
361
362 try {
363 m1();
364 } catch (CErrnoTemplException<CCoreException>& e) {
365 NCBI_REPORT_EXCEPTION("caught as CErrnoTemplException<CCoreException>", e);
366 assert((int)e.GetErrCode() == (int)CException::eInvalid);
367 } catch (CCoreException& e) {
368 NCBI_REPORT_EXCEPTION("caught as CCoreException", e);
369 assert((int)e.GetErrCode() == (int)CException::eInvalid);
370 } catch (exception&) {
371 assert(0);
372 }
373
374 try {
375 tp1();
376 } catch (CParseTemplException<CCoreException>& e) {
377 NCBI_REPORT_EXCEPTION("caught as CParseTemplException<CCoreException>", e);
378 assert(e.GetErrCode() == CParseTemplException<CCoreException>::eErr);
379 } catch (exception&) {
380 assert(0);
381 }
382
383 LOG_POST("Test completed");
384 return 0;
385 }
386
387 END_NCBI_SCOPE
388
389
390
391 /////////////////////////////////////////////////////////////////////////////
392 // MAIN
393
394 USING_NCBI_SCOPE;
395
main(int argc,const char * argv[])396 int main(int argc, const char* argv[])
397 {
398 return CExceptApplication().AppMain(argc, argv);
399 }
400