#include "xxl.h" #include #define FAIL(why) \ do { \ fprintf(stderr, "%s\n", (why)); \ exit(1); \ } while (0) typedef struct { int cleaned; } test_asset_t; static void cleanup_test_asset(void *asset, void *arg) { ((test_asset_t *)asset)->cleaned = 1; } static void test_catch(void) { int caught, pass; for (pass = 0; pass < 3; pass++) { XXL_TRY_BEGIN { caught = 0; switch (pass) { case 0: XXL_THROW_ERROR(0x42174217, NULL); case 1: XXL_THROW_ERROR(0x17421742, NULL); case 2: break; } } XXL_CATCH(0x42174217) { caught = 1; } XXL_EXCEPT { caught = 2; } XXL_TRY_END; switch (pass) { case 0: if (caught == 0) FAIL("Did not catch exception 0x42174217\n"); if (caught == 2) FAIL("Caught 0x42174217 as 0x17421742\n"); if (caught != 1) FAIL("(catch pass 0) 'caught' is totally wrong!\n"); break; case 1: if (caught == 0) FAIL("Did not catch exception 0x17421742\n"); if (caught == 1) FAIL("Caught 0x17421742 as 0x42174217\n"); if (caught != 2) FAIL("(catch pass 1) 'caught' is totally wrong!\n"); break; default: if (caught != 0) FAIL("Exception caught when none thrown\n"); break; } } } static void test_finally(void) { int caught, finally, pass; for (pass = 0; pass < 3; pass++) { XXL_TRY_BEGIN { caught = finally = 0; switch (pass) { case 0: break; case 1: XXL_THROW_ERROR(0x42174217, NULL); case 2: XXL_THROW_ERROR(0x17421742, NULL); } } XXL_CATCH(0x42174217) { caught = 1; } XXL_EXCEPT { caught = 2; } XXL_FINALLY { finally = 1; } XXL_TRY_END; switch (pass) { case 0: if (caught == 1) FAIL("Caught 0x42174217 when none thrown with finally\n"); if (caught == 2) FAIL("Caught 0x17421742 when none thrown with finally\n"); if (caught != 0) FAIL("(finally pass 0) 'caught' is totally wrong!\n"); if (!finally) FAIL("Finally failed to run when no exception thrown\n"); break; case 1: if (caught == 0) FAIL("Did not catch exception 0x42174217 with finally\n"); if (caught == 2) FAIL("Caught 0x42174217 as 0x17421742 with finally\n"); if (caught != 1) FAIL("(finally pass 1) 'caught' is totally wrong!\n"); if (!finally) FAIL("Finally failed to run when specific exception caught\n"); break; case 2: if (caught == 0) FAIL("Did not catch exception 0x17421742 with finally\n"); if (caught == 1) FAIL("Caught 0x17421742 as 0x42174217 with finally\n"); if (caught != 2) FAIL("(finally pass 2) 'caught' is totally wrong!\n"); if (!finally) FAIL("Finally failed to run when non-specific exception caught\n"); break; } } } static void test_assets(void) { int pass; test_asset_t asset; xxl_assettype_t type; for (pass = 0; pass < 8; pass++) { XXL_TRY_BEGIN { asset.cleaned = 0; switch (pass) { case 0: case 4: type = XXL_ASSET_PERMANENT; break; case 1: case 5: type = XXL_ASSET_TEMPORARY; break; case 2: case 6: type = XXL_ASSET_PROMOTE; break; case 3: case 7: type = XXL_ASSET_DEMOTE; break; } XXL_ASSET_SAVE(&asset, cleanup_test_asset, NULL, type); if (pass > 3) XXL_THROW_ERROR(0x42174217, NULL); } XXL_EXCEPT {} XXL_TRY_END; switch (pass) { case 0: if (asset.cleaned) FAIL("PERMANENT asset cleaned; no exception thrown\n"); break; case 1: if (!asset.cleaned) FAIL("TEMPORARY asset NOT cleaned; no exception thrown\n"); break; case 2: if (asset.cleaned) FAIL("PROMOTE asset cleaned; no exception thrown\n"); break; case 3: if (!asset.cleaned) FAIL("DEMOTE asset NOT cleaned; no exception thrown\n"); break; case 4: if (asset.cleaned) FAIL("PERMANENT asset cleaned; exception thrown\n"); break; case 5: if (!asset.cleaned) FAIL("TEMPORARY asset NOT cleaned; exception thrown\n"); break; case 6: if (!asset.cleaned) FAIL("PROMOTE asset NOT cleaned; exception thrown\n"); break; case 7: if (asset.cleaned) FAIL("DEMOTE asset cleaned; exception thrown\n"); break; } } } static void test_nested(void) { int caught, inner_finally, outer_finally, pass; for (pass = 0; pass < 2; pass++) { XXL_TRY_BEGIN { caught = inner_finally = outer_finally = 0; XXL_TRY_BEGIN { switch (pass) { case 0: XXL_THROW_ERROR(0x42174217, NULL); case 1: XXL_THROW_ERROR(0x17421742, NULL); } } XXL_CATCH(0x42174217) { XXL_RETHROW_ERROR(); } XXL_FINALLY { inner_finally = 1; } XXL_TRY_END; } XXL_CATCH(0x42174217) { caught = 1; } XXL_CATCH(0x17421742) { caught = 2; } XXL_FINALLY { outer_finally = 1; } XXL_TRY_END; switch (pass) { case 0: if (caught == 0) FAIL("Outer try did not catch 0x42174217\n"); if (caught == 2) FAIL("Outer try caught 0x42174217 as 0x17421742\n"); if (caught != 1) FAIL("(nested pass 0) 'caught' is totally wrong!\n"); if (!inner_finally) FAIL("(nested pass 0) Inner finally block did not run\n"); if (!outer_finally) FAIL("(nested pass 0) Outer finally block did not run\n"); break; case 1: if (caught == 0) FAIL("Outer try did not catch 0x17421742\n"); if (caught == 1) FAIL("Outer try caught 0x17421742 as 0x42174217\n"); if (caught != 2) FAIL("(nested pass 1) 'caught' is totally wrong!\n"); if (!inner_finally) FAIL("(nested pass 1) Inner finally block did not run\n"); if (!outer_finally) FAIL("(nested pass 1) Outer finally block did not run\n"); break; } } } int main(int argc, char *agrv[]) { printf("Testing simple exception catching ...\n"); test_catch(); printf("Testing simple finally block execution ...\n"); test_finally(); printf("Testing simple asset management ...\n"); test_assets(); printf("Testing nested exception handling ...\n"); test_nested(); exit(0); return 0; }