• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  //  (C) Copyright Gennadiy Rozental 2003-2014.
2  //  Distributed under the Boost Software License, Version 1.0.
3  //  (See accompanying file LICENSE_1_0.txt or copy at
4  //  http://www.boost.org/LICENSE_1_0.txt)
5  
6  //  See http://www.boost.org/libs/test for the library home page.
7  
8  #include <boost/test/prg_exec_monitor.hpp>
9  #include <boost/test/execution_monitor.hpp>
10  #include <boost/test/utils/basic_cstring/io.hpp>
11  
12  #include <iostream>
13  
14  struct my_exception1
15  {
my_exception1my_exception116      explicit    my_exception1( int res_code ) : m_res_code( res_code ) {}
17  
18      int         m_res_code;
19  };
20  
21  struct my_exception2
22  {
my_exception2my_exception223      explicit    my_exception2( int res_code ) : m_res_code( res_code ) {}
24  
25      int         m_res_code;
26  };
27  
28  namespace {
29  
30  class dangerous_call {
31  public:
dangerous_call(int argc)32      dangerous_call( int argc ) : m_argc( argc ) {}
33  
operator ()()34      int operator()()
35      {
36          // here we perform some operation under monitoring that could throw my_exception
37          if( m_argc < 2 )
38              throw my_exception1( 23 );
39          if( m_argc > 3 )
40              throw my_exception2( 45 );
41          else if( m_argc > 2 )
42              throw "too many args";
43  
44          return 1;
45      }
46  
47  private:
48      // Data members
49      int     m_argc;
50  };
51  
translate_my_exception1(my_exception1 const & ex)52  void translate_my_exception1( my_exception1 const& ex )
53  {
54      std::cout << "Caught my_exception1(" << ex.m_res_code << ")"<< std::endl;
55  }
56  
translate_my_exception2(my_exception2 const & ex)57  void translate_my_exception2( my_exception2 const& ex )
58  {
59      std::cout << "Caught my_exception2(" << ex.m_res_code << ")"<< std::endl;
60  }
61  
generate_fpe()62  int generate_fpe()
63  {
64      double d = 0.0;
65  
66      d = 1/d;
67  
68      return 0;
69  }
70  
generate_fpe2()71  int generate_fpe2()
72  {
73      double d = 1e158;
74  
75      d = d*d;
76  
77      return 0;
78  }
79  
generate_fpe3()80  int generate_fpe3()
81  {
82      double d = 1.1e-308;
83  
84      d = 1/d;
85  
86      return 0;
87  }
88  
generate_int_div_0()89  int generate_int_div_0()
90  {
91      int i = 0;
92  
93      return 1/i;
94  }
95  
96  #if (defined(__clang__) && __clang_major__ >= 6) || (defined(__GNUC__) && __GNUC__ >= 8)
97  __attribute__((no_sanitize("null")))
98  #endif
generate_sigfault()99  int generate_sigfault()
100  {
101      int* p = 0;
102  
103      return *p;
104  }
105  
106  
107  } // local_namespace
108  
109  int
cpp_main(int argc,char * [])110  cpp_main( int argc , char *[] )
111  {
112      ::boost::execution_monitor ex_mon;
113  
114      ///////////////////////////////////////////////////////////////
115  
116      ex_mon.register_exception_translator<my_exception1>( &translate_my_exception1, "except1" );
117      ex_mon.register_exception_translator<my_exception2>( &translate_my_exception2, "except2" );
118  
119      try {
120          ex_mon.execute( dangerous_call( argc ) );
121          std::cout << "Should reach this line " << __LINE__ << std::endl;
122      }
123      catch ( boost::execution_exception const& ex ) {
124          std::cout << "Caught exception: " << ex.what() << std::endl;
125      }
126  
127      ///////////////////////////////////////////////////////////////
128  
129      ex_mon.erase_exception_translator( "except2" );
130  
131      try {
132          ex_mon.execute( dangerous_call( 5 ) );
133          std::cout << "Should not reach this line " << __LINE__ << std::endl;
134      }
135      catch ( boost::execution_exception const& ex ) {
136          std::cout << "Caught exception: " << ex.what() << std::endl;
137      }
138  
139      ///////////////////////////////////////////////////////////////
140  
141      ex_mon.erase_exception_translator<my_exception1>();
142  
143      try {
144          ex_mon.execute( dangerous_call( 1 ) );
145          std::cout << "Should not reach this line " << __LINE__ << std::endl;
146      }
147      catch ( boost::execution_exception const& ex ) {
148          std::cout << "Caught exception: " << ex.what() << std::endl;
149      }
150  
151      ///////////////////////////////////////////////////////////////
152  
153  // we are currently not able to silence those errors below with UBSAN under clang
154  // this seems to come from the way clang handles floating point exceptions + UB.
155  #if !(defined(HAS_UBSAN) && (HAS_UBSAN==1) && defined(__clang__))
156  
157      ex_mon.p_detect_fp_exceptions.value = boost::fpe::BOOST_FPE_DIVBYZERO;
158      ex_mon.p_catch_system_errors.value = false;
159  
160      try {
161          ex_mon.execute( &generate_fpe );
162          std::cout << "Should not reach this line " << __LINE__ << std::endl;
163      }
164      catch ( boost::execution_exception const& ex ) {
165          std::cout << "Caught exception: " << ex.what() << std::endl;
166      }
167  
168      ///////////////////////////////////////////////////////////////
169  
170      ex_mon.p_detect_fp_exceptions.value = boost::fpe::BOOST_FPE_ALL;
171  
172      try {
173          ex_mon.execute( &generate_fpe2 );
174          std::cout << "Should not reach this line " << __LINE__ << std::endl;
175      }
176      catch ( boost::execution_exception const& ex ) {
177          std::cout << "Caught exception: " << ex.what() << std::endl;
178      }
179  
180      try {
181          ex_mon.execute( &generate_fpe3 );
182          std::cout << "Should not reach this line " << __LINE__ << std::endl;
183      }
184      catch ( boost::execution_exception const& ex ) {
185          std::cout << "Caught exception: " << ex.what() << std::endl;
186      }
187  
188      ///////////////////////////////////////////////////////////////
189  
190      ex_mon.p_detect_fp_exceptions.value = boost::fpe::BOOST_FPE_OFF;
191      ex_mon.p_catch_system_errors.value = true;
192  
193      try {
194          ex_mon.execute( &generate_int_div_0 );
195          std::cout << "Should not reach this line " << __LINE__ << std::endl;
196      }
197      catch ( boost::execution_exception const& ex ) {
198          std::cout << "Caught exception: " << ex.what() << std::endl;
199      }
200  
201      ///////////////////////////////////////////////////////////////
202  
203      ex_mon.p_detect_fp_exceptions.value = boost::fpe::BOOST_FPE_OFF;
204      ex_mon.p_catch_system_errors.value = true;
205  
206      try {
207          ex_mon.execute( &generate_sigfault );
208          std::cout << "Should not reach this line " << __LINE__ << std::endl;
209      }
210      catch ( boost::execution_exception const& ex ) {
211          std::cout << "Caught exception: " << ex.what() << std::endl;
212      }
213  #endif // UBSAN issue
214  
215      return 0;
216  }
217  
218  // EOF
219