Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:42

0001 /*
0002  *  This routine is the initialization task for this test program.
0003  *  It is called from init_exec and has the responsibility for creating
0004  *  and starting the tasks that make up the test.  If the time of day
0005  *  clock is required for the test, it should also be set to a known
0006  *  value by this function.
0007  *
0008  *  Input parameters:  NONE
0009  *
0010  *  Output parameters:  NONE
0011  *
0012  *  COPYRIGHT (c) 1994 by Division Incorporated
0013  *  Based in part on OAR works.
0014  *
0015  *  The license and distribution terms for this file may be
0016  *  found in the file LICENSE in this distribution or at
0017  *  http://www.rtems.org/license/LICENSE.
0018  *
0019  *
0020  *  by Rosimildo da Silva:
0021  *  Modified the test a bit to indicate when an instance is
0022  *  global or not, and added code to test C++ exception.
0023  */
0024 
0025 #include <rtems.h>
0026 #include <rtems/bspIo.h>
0027 #include <rtems/test-info.h>
0028 #include <rtems/sysinit.h>
0029 
0030 #include <cstdio>
0031 #include <cstdlib>
0032 #include <cstring>
0033 #include <stdexcept>
0034 
0035 #ifdef RTEMS_TEST_IO_STREAM
0036 #include <iostream>
0037 #endif
0038 
0039 const char rtems_test_name[] = "CONSTRUCTOR/DESTRUCTOR";
0040 
0041 extern "C"
0042 {
0043 #include <tmacros.h>
0044 extern rtems_task main_task(rtems_task_argument);
0045 }
0046 
0047 static int num_inst = 0;
0048 
0049 static void check_end_of_test(void)
0050 {
0051   if ( num_inst == 0 ) {
0052     TEST_END();
0053   }
0054 }
0055 
0056 class AClass {
0057 public:
0058   AClass(const char *p = "LOCAL" ) : ptr( p )
0059     {
0060         num_inst++;
0061         printf(
0062           "%s: Hey I'm in base class constructor number %d for %p.\n",
0063           p, num_inst, this
0064         );
0065 
0066     /*
0067      * Make sure we use some space
0068      */
0069 
0070         string = new char[50];
0071     sprintf(string, "Instantiation order %d", num_inst);
0072     };
0073 
0074     virtual ~AClass()
0075     {
0076     // MUST USE PRINTK -- RTEMS IS SHUTTING DOWN WHEN THIS RUNS
0077         printk(
0078           "%s: Hey I'm in base class destructor number %d for %p.\n",
0079           ptr, num_inst, this
0080         );
0081         printk("Derived class - %s\n", string);
0082         num_inst--;
0083         check_end_of_test();
0084     };
0085 
0086 #if __cplusplus >= 201103L
0087     AClass& operator=(const AClass&) = default;
0088 #endif
0089 
0090     virtual void print()  { printf("%s\n", string); };
0091 
0092 protected:
0093     char  *string;
0094     const char *ptr;
0095 };
0096 
0097 class BClass : public AClass {
0098 public:
0099   BClass(const char *p = "LOCAL" ) : AClass( p )
0100     {
0101         num_inst++;
0102         printf(
0103           "%s: Hey I'm in derived class constructor number %d for %p.\n",
0104           p, num_inst,  this
0105         );
0106 
0107     /*
0108      * Make sure we use some space
0109      */
0110 
0111         string = new char[50];
0112     sprintf(string, "Instantiation order %d", num_inst);
0113     };
0114 
0115     ~BClass()
0116     {
0117         printk(
0118           "%s: Hey I'm in derived class destructor number %d for %p.\n",
0119           ptr, num_inst,
0120           this
0121         );
0122         printk("Derived class - %s\n", string);
0123         num_inst--;
0124         check_end_of_test();
0125     };
0126 
0127     void print()  { printf("Derived class - %s\n", string); }
0128 };
0129 
0130 
0131 class RtemsException
0132 {
0133 public:
0134 
0135     RtemsException( const char *module, int ln, int err = 0 )
0136     : error( err ), line( ln ), file( module )
0137     {
0138       printf( "RtemsException raised=File:%s, Line:%d, Error=%X\n",
0139                file, line, error );
0140     }
0141 
0142     void show()
0143     {
0144       printf( "RtemsException ---> File:%s, Line:%d, Error=%X\n",
0145                file, line, error );
0146     }
0147 
0148 private:
0149    int  error;
0150    int  line;
0151    const char *file;
0152 
0153 };
0154 
0155 
0156 
0157 AClass foo( "GLOBAL" );
0158 BClass foobar( "GLOBAL" );
0159 
0160 void
0161 cdtest(void)
0162 {
0163     AClass bar, blech, blah;
0164     BClass bleak;
0165 
0166 #ifdef RTEMS_TEST_IO_STREAM
0167     std::cout << "Testing a C++ I/O stream" << std::endl;
0168 #else
0169     printf("IO Stream not tested\n");
0170 #endif
0171     bar = blech;
0172     rtems_task_wake_after( 5 * rtems_clock_get_ticks_per_second() );
0173 }
0174 
0175 //
0176 // main equivalent
0177 //      It can not be called 'main' since the bsp owns that name
0178 //      in many implementations in order to get global constructors
0179 //      run.
0180 //
0181 
0182 static void foo_function()
0183 {
0184     try
0185     {
0186       throw "foo_function() throw this exception";
0187     }
0188     catch( const char *e )
0189     {
0190      printf( "foo_function() catch block called:\n   < %s  >\n", e );
0191      throw "foo_function() re-throwing execption...";
0192     }
0193 }
0194 
0195 rtems_task main_task(
0196   rtems_task_argument
0197 )
0198 {
0199     cdtest();
0200 
0201     printf( "*** TESTING C++ EXCEPTIONS ***\n\n" );
0202 
0203     try
0204     {
0205       foo_function();
0206     }
0207     catch( const char *e )
0208     {
0209        printf( "Success catching a char * exception\n%s\n", e );
0210     }
0211 
0212     try
0213     {
0214       throw std::runtime_error("thrown std::runtime object");
0215     }
0216     catch (std::exception const& e)
0217     {
0218        printf("throw std::runtime: caught: %s\n", e.what());
0219     }
0220 
0221     try
0222     {
0223       printf( "throw an instance based exception\n" );
0224         throw RtemsException( __FILE__, __LINE__, 0x55 );
0225     }
0226     catch( RtemsException & ex )
0227     {
0228        printf( "Success catching RtemsException...\n" );
0229        ex.show();
0230     }
0231     catch(...)
0232     {
0233       printf( "Caught another exception.\n" );
0234     }
0235     printf( "Exceptions are working properly.\n" );
0236     rtems_task_wake_after( 5 * rtems_clock_get_ticks_per_second() );
0237     printf( "Global Dtors should be called after this line....\n" );
0238     exit(0);
0239 }
0240 
0241 /*
0242  * Exceptions during system initialization work only on targets which do not
0243  * need a registration of exception frames during the global construction.  In
0244  * particular, targets which use the DWARF2 unwinder cannot use exceptions
0245  * during system initialization.
0246  */
0247 #if defined(__arm__)
0248 #define CAN_DO_EXCEPTIONS_DURING_SYSINIT
0249 #endif
0250 
0251 #ifdef CAN_DO_EXCEPTIONS_DURING_SYSINIT
0252 static void early_exception()
0253 {
0254     try
0255     {
0256       throw "early exception";
0257     }
0258     catch( const char *e )
0259     {
0260       rtems_test_assert(strcmp(e, "early exception") == 0);
0261       throw "early exception 2";
0262     }
0263 }
0264 #endif
0265 
0266 static void test_exceptions_during_system_init()
0267 {
0268     TEST_BEGIN();
0269 
0270 #ifdef CAN_DO_EXCEPTIONS_DURING_SYSINIT
0271     try
0272     {
0273       early_exception();
0274     }
0275     catch( const char *e )
0276     {
0277       rtems_test_assert(strcmp(e, "early exception 2") == 0);
0278     }
0279 #endif
0280 }
0281 
0282 RTEMS_SYSINIT_ITEM(
0283     test_exceptions_during_system_init,
0284     RTEMS_SYSINIT_IDLE_THREADS,
0285     RTEMS_SYSINIT_ORDER_LAST
0286 );