libcxxrt

git clone https://git.neptards.moe/neptards/libcxxrt.git
Log | Files | Refs | README | LICENSE

test_exception.cc (5456B)


      1 #include "test.h"
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <stdint.h>
      5 
      6 #include <exception>
      7 
      8 #define fprintf(...)
      9 
     10 void log(void* ignored)
     11 {
     12 	//printf("Cleanup called on %s\n", *(char**)ignored);
     13 }
     14 #define CLEANUP\
     15 	__attribute__((cleanup(log))) __attribute__((unused))\
     16 		const char *f = __func__;
     17 
     18 /**
     19  * Simple struct to test throwing.
     20  */
     21 struct foo
     22 {
     23 	int i;
     24 };
     25 
     26 struct bar : foo
     27 {
     28 	float bar;
     29 };
     30 
     31 
     32 /**
     33  * Non-pod type to test throwing
     34  */
     35 class non_pod {
     36 public:
     37     non_pod(int i): x(i) {}
     38     int x;
     39 };
     40 
     41 
     42 static int cleanup_count;
     43 /**
     44  * Simple structure declared with a destructor.  Destroying this object will
     45  * increment cleanup count.  The destructor should be called automatically if
     46  * an instance of cl is allocated with automatic storage.
     47  */
     48 struct cl
     49 {
     50 	int i;
     51 	~cl() { fprintf(stderr, "cl destroyed: %d\n", i); cleanup_count++; }
     52 };
     53 /**
     54  * Test that one cl was destroyed when running the argument.
     55  */
     56 #define TEST_CLEANUP(x) do {\
     57 		int cleanups = cleanup_count;\
     58 		{ x; }\
     59 		TEST(cleanup_count == cleanups+1, "Cleanup ran correctly");\
     60 	} while(0)
     61 
     62 int inner(int i)
     63 {
     64 	CLEANUP
     65 	switch (i)
     66 	{
     67 		case 0: throw (int)1.0;
     68 		case 1: throw (float)1.0;
     69 		case 2: fprintf(stderr, "Throwing int64_t\n");throw (int64_t)1;
     70 		case 3: { foo f = {2} ; throw f; }
     71 		case 4: { bar f; f.i = 2 ; f.bar=1 ; throw f; }
     72         case 5: throw non_pod(3);
     73 	}
     74 	return -1;
     75 }
     76 
     77 int outer(int i) throw(float, int, foo, non_pod)
     78 {
     79 	//CLEANUP
     80 	inner(i);
     81 	return 1;
     82 }
     83 
     84 static void test_const(void)
     85 {
     86 	int a = 1;
     87 	try
     88 	{
     89 		throw a;
     90 	}
     91 	catch (const int b)
     92 	{
     93 		TEST(a == b, "Caught int as const int");
     94 	}
     95 	catch(...)
     96 	{
     97 		TEST(0, "Failed to catch int as const int");
     98 	}
     99 	try
    100 	{
    101 		throw &a;
    102 	}
    103 	catch (const int *b)
    104 	{
    105 		TEST(&a == b, "Caught int* as const int*");
    106 	}
    107 	catch(...)
    108 	{
    109 		TEST(0, "Failed to catch int* as const int*");
    110 	}
    111 }
    112 
    113 static void test_catch(int s) 
    114 {
    115 	cl c;
    116 	c.i = 12;
    117 	fprintf(stderr, "Entering try\n");
    118 	try
    119 	{
    120 		outer(s);
    121 	}
    122 	catch(int i)
    123 	{
    124 		fprintf(stderr, "Caught int %d in test %d\n", i, s);
    125 		TEST((s == 0 && i == 1) || (s == 2 && i == 0), "Caught int");
    126 		return;
    127 	}
    128 	catch (float f)
    129 	{
    130 		fprintf(stderr, "Caught float %f!\n", f);
    131 		TEST(s == 1 && f == 1, "Caught float");
    132 		return;
    133 	}
    134 	catch (foo f)
    135 	{
    136 		fprintf(stderr, "Caught struct {%d}!\n", f.i);
    137 		TEST((s == 3 || s == 4) && f.i == 2, "Caught struct");
    138 		return;
    139 	}
    140     catch (non_pod np) {
    141         fprintf(stderr, "Caught non_pod {%d}!\n", np.x);
    142         TEST(s == 5 && np.x == 3, "Caught non_pod");
    143         return;
    144     }
    145 	//abort();
    146 	TEST(0, "Unreachable line reached");
    147 }
    148 
    149 void test_nested1(void)
    150 {
    151 	CLEANUP;
    152 	cl c;
    153 	c.i = 123;
    154 	try 
    155 	{
    156 		outer(0);
    157 	}
    158 	catch (int a)
    159 	{
    160 		try
    161 		{
    162 			TEST(a == 1, "Caught int");
    163 			outer(1);
    164 		}
    165 		catch (float f)
    166 		{
    167 			TEST(f == 1, "Caught float inside outer catch block");
    168 			throw;
    169 		}
    170 	}
    171 }
    172 
    173 void test_nested()
    174 {
    175 	try
    176 	{
    177 		test_nested1();
    178 	}
    179 	catch (float f)
    180 	{
    181 		fprintf(stderr, "Caught re-thrown float\n");
    182 		TEST(f == 1, "Caught re-thrown float");
    183 	}
    184 }
    185 
    186 static int violations = 0;
    187 static void throw_zero()
    188 {
    189 	violations++;
    190 	fprintf(stderr, "Throwing 0\n");
    191 	throw 0;
    192 }
    193 
    194 struct uncaught_exception_checker
    195 {
    196 	uncaught_exception_checker(bool uncaught) : m_uncaught(uncaught) {}
    197 	~uncaught_exception_checker() {
    198 		if (std::uncaught_exception())
    199 			TEST(m_uncaught, "At least one uncaught exception is in flight");
    200 		else
    201 			TEST(!m_uncaught, "No uncaught exceptions are in flight");
    202 	}
    203 	bool m_uncaught;
    204 };
    205 
    206 void test_uncaught_exception()
    207 {
    208 	uncaught_exception_checker outer(false);
    209 	try {
    210 		uncaught_exception_checker inner(true);
    211 		throw 42;
    212 	}
    213 	catch (...) {}
    214 }
    215 
    216 struct uncaught_exceptions_checker
    217 {
    218 	uncaught_exceptions_checker(int uncaught) : m_uncaught(uncaught) {}
    219 	~uncaught_exceptions_checker() {
    220 		char msg[128];
    221 		int uncaught = std::uncaught_exceptions();
    222 		snprintf(msg, sizeof msg, "%d uncaught exception%s in flight",
    223 		    uncaught, uncaught == 1 ? " is" : "s are");
    224 		TEST(uncaught == m_uncaught, msg);
    225 	}
    226 	int m_uncaught;
    227 };
    228 
    229 class top {
    230 public:
    231 	~top() {
    232 		try {
    233 			uncaught_exceptions_checker uec(4);
    234 			throw "top";
    235 		}
    236 		catch (...) {}
    237 	}
    238 };
    239 
    240 class middle {
    241 public:
    242 	~middle() {
    243 		try {
    244 			top f;
    245 			uncaught_exceptions_checker uec(3);
    246 			throw "middle";
    247 		}
    248 		catch (...) {}
    249 	}
    250 };
    251 
    252 class bottom {
    253 public:
    254 	~bottom() {
    255 		try {
    256 			middle f;
    257 			uncaught_exceptions_checker uec(2);
    258 			throw "bottom";
    259 		}
    260 		catch (...) {}
    261 	}
    262 };
    263 
    264 void test_uncaught_exceptions()
    265 {
    266 	uncaught_exceptions_checker outer(0);
    267 	try {
    268 		bottom b;
    269 		uncaught_exceptions_checker inner(1);
    270 		throw "test";
    271 	}
    272 	catch (...) {}
    273 }
    274 
    275 extern "C" void __cxa_bad_cast();
    276 
    277 void test_exceptions(void)
    278 {
    279 	std::set_unexpected(throw_zero);
    280 	TEST_CLEANUP(test_catch(0));
    281 	TEST_CLEANUP(test_catch(1));
    282 	TEST_CLEANUP(test_catch(3));
    283 	TEST_CLEANUP(test_catch(4));
    284 	TEST_CLEANUP(test_catch(5));
    285 	TEST_CLEANUP(test_nested());
    286 	try{
    287 		test_catch(2);
    288 		TEST(violations == 1, "Exactly one exception spec violation");
    289 	}
    290 	catch (int64_t i) {
    291 		TEST(0, "Caught int64_t, but that violates an exception spec");
    292 	}
    293 	int a;
    294 	try {
    295 		throw &a;
    296 	}
    297 	catch (const int *b)
    298 	{
    299 		TEST(&a==b, "Caught const int from thrown int");
    300 	}
    301 	try {
    302 		throw &a;
    303 	}
    304 	catch (int *b)
    305 	{
    306 		TEST(&a==b, "Caught int from thrown int");
    307 	}
    308 	try
    309 	{
    310 		__cxa_bad_cast();
    311 	}
    312 	catch (std::exception b)
    313 	{
    314 		TEST(1, "Caught bad cast");
    315 	}
    316 	catch (...)
    317 	{
    318 		TEST(0, "Bad cast was not caught correctly");
    319 	}
    320 	test_const();
    321 	test_uncaught_exception();
    322 	test_uncaught_exceptions();
    323 
    324 
    325 	//printf("Test: %s\n",
    326 }