289 lines
4.9 KiB
C
289 lines
4.9 KiB
C
|
/* $Id$ */
|
||
|
/*
|
||
|
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
|
||
|
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation; either version 2 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program; if not, write to the Free Software
|
||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
*/
|
||
|
#include "test.h"
|
||
|
|
||
|
|
||
|
/**
|
||
|
* \page page_pjlib_exception_test Test: Exception Handling
|
||
|
*
|
||
|
* This file provides implementation of \b exception_test(). It tests the
|
||
|
* functionality of the exception handling API.
|
||
|
*
|
||
|
* @note This test use static ID not acquired through proper registration.
|
||
|
* This is not recommended, since it may create ID collissions.
|
||
|
*
|
||
|
* \section exception_test_sec Scope of the Test
|
||
|
*
|
||
|
* Some scenarios tested:
|
||
|
* - no exception situation
|
||
|
* - basic TRY/CATCH
|
||
|
* - multiple exception handlers
|
||
|
* - default handlers
|
||
|
*
|
||
|
*
|
||
|
* This file is <b>pjlib-test/exception.c</b>
|
||
|
*
|
||
|
* \include pjlib-test/exception.c
|
||
|
*/
|
||
|
|
||
|
|
||
|
#if INCLUDE_EXCEPTION_TEST
|
||
|
|
||
|
#include <pjlib.h>
|
||
|
|
||
|
#ifdef _MSC_VER
|
||
|
#pragma warning(disable:4702) // warning C4702: unreachable code
|
||
|
#endif
|
||
|
|
||
|
#define ID_1 1
|
||
|
#define ID_2 2
|
||
|
|
||
|
static int throw_id_1(void)
|
||
|
{
|
||
|
PJ_THROW( ID_1 );
|
||
|
PJ_UNREACHED(return -1;)
|
||
|
}
|
||
|
|
||
|
static int throw_id_2(void)
|
||
|
{
|
||
|
PJ_THROW( ID_2 );
|
||
|
PJ_UNREACHED(return -1;)
|
||
|
}
|
||
|
|
||
|
static int try_catch_test(void)
|
||
|
{
|
||
|
PJ_USE_EXCEPTION;
|
||
|
int rc = -200;
|
||
|
|
||
|
PJ_TRY {
|
||
|
PJ_THROW(ID_1);
|
||
|
}
|
||
|
PJ_CATCH_ANY {
|
||
|
rc = 0;
|
||
|
}
|
||
|
PJ_END;
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
static int throw_in_handler(void)
|
||
|
{
|
||
|
PJ_USE_EXCEPTION;
|
||
|
int rc = 0;
|
||
|
|
||
|
PJ_TRY {
|
||
|
PJ_THROW(ID_1);
|
||
|
}
|
||
|
PJ_CATCH_ANY {
|
||
|
if (PJ_GET_EXCEPTION() != ID_1)
|
||
|
rc = -300;
|
||
|
else
|
||
|
PJ_THROW(ID_2);
|
||
|
}
|
||
|
PJ_END;
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
static int return_in_handler(void)
|
||
|
{
|
||
|
PJ_USE_EXCEPTION;
|
||
|
|
||
|
PJ_TRY {
|
||
|
PJ_THROW(ID_1);
|
||
|
}
|
||
|
PJ_CATCH_ANY {
|
||
|
return 0;
|
||
|
}
|
||
|
PJ_END;
|
||
|
return -400;
|
||
|
}
|
||
|
|
||
|
|
||
|
static int test(void)
|
||
|
{
|
||
|
int rc = 0;
|
||
|
PJ_USE_EXCEPTION;
|
||
|
|
||
|
/*
|
||
|
* No exception situation.
|
||
|
*/
|
||
|
PJ_TRY {
|
||
|
PJ_UNUSED_ARG(rc);
|
||
|
}
|
||
|
PJ_CATCH_ANY {
|
||
|
rc = -3;
|
||
|
}
|
||
|
PJ_END;
|
||
|
|
||
|
if (rc != 0)
|
||
|
return rc;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Basic TRY/CATCH
|
||
|
*/
|
||
|
PJ_TRY {
|
||
|
rc = throw_id_1();
|
||
|
|
||
|
// should not reach here.
|
||
|
rc = -10;
|
||
|
}
|
||
|
PJ_CATCH_ANY {
|
||
|
int id = PJ_GET_EXCEPTION();
|
||
|
if (id != ID_1) {
|
||
|
PJ_LOG(3,("", "...error: got unexpected exception %d (%s)",
|
||
|
id, pj_exception_id_name(id)));
|
||
|
if (!rc) rc = -20;
|
||
|
}
|
||
|
}
|
||
|
PJ_END;
|
||
|
|
||
|
if (rc != 0)
|
||
|
return rc;
|
||
|
|
||
|
/*
|
||
|
* Multiple exceptions handlers
|
||
|
*/
|
||
|
PJ_TRY {
|
||
|
rc = throw_id_2();
|
||
|
// should not reach here.
|
||
|
rc = -25;
|
||
|
}
|
||
|
PJ_CATCH_ANY {
|
||
|
switch (PJ_GET_EXCEPTION()) {
|
||
|
case ID_1:
|
||
|
if (!rc) rc = -30;
|
||
|
break;
|
||
|
case ID_2:
|
||
|
if (!rc) rc = 0;
|
||
|
break;
|
||
|
default:
|
||
|
if (!rc) rc = -40;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
PJ_END;
|
||
|
|
||
|
if (rc != 0)
|
||
|
return rc;
|
||
|
|
||
|
/*
|
||
|
* Test default handler.
|
||
|
*/
|
||
|
PJ_TRY {
|
||
|
rc = throw_id_1();
|
||
|
// should not reach here
|
||
|
rc = -50;
|
||
|
}
|
||
|
PJ_CATCH_ANY {
|
||
|
switch (PJ_GET_EXCEPTION()) {
|
||
|
case ID_1:
|
||
|
if (!rc) rc = 0;
|
||
|
break;
|
||
|
default:
|
||
|
if (!rc) rc = -60;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
PJ_END;
|
||
|
|
||
|
if (rc != 0)
|
||
|
return rc;
|
||
|
|
||
|
/*
|
||
|
* Nested handlers
|
||
|
*/
|
||
|
PJ_TRY {
|
||
|
rc = try_catch_test();
|
||
|
}
|
||
|
PJ_CATCH_ANY {
|
||
|
rc = -70;
|
||
|
}
|
||
|
PJ_END;
|
||
|
|
||
|
if (rc != 0)
|
||
|
return rc;
|
||
|
|
||
|
/*
|
||
|
* Throwing exception inside handler
|
||
|
*/
|
||
|
rc = -80;
|
||
|
PJ_TRY {
|
||
|
int rc2;
|
||
|
rc2 = throw_in_handler();
|
||
|
if (rc2)
|
||
|
rc = rc2;
|
||
|
}
|
||
|
PJ_CATCH_ANY {
|
||
|
if (PJ_GET_EXCEPTION() == ID_2) {
|
||
|
rc = 0;
|
||
|
} else {
|
||
|
rc = -90;
|
||
|
}
|
||
|
}
|
||
|
PJ_END;
|
||
|
|
||
|
if (rc != 0)
|
||
|
return rc;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Return from handler. Returning from the function inside a handler
|
||
|
* should be okay (though returning from the function inside the
|
||
|
* PJ_TRY block IS NOT OKAY!!). We want to test to see if handler
|
||
|
* is cleaned up properly, but not sure how to do this.
|
||
|
*/
|
||
|
PJ_TRY {
|
||
|
int rc2;
|
||
|
rc2 = return_in_handler();
|
||
|
if (rc2)
|
||
|
rc = rc2;
|
||
|
}
|
||
|
PJ_CATCH_ANY {
|
||
|
rc = -100;
|
||
|
}
|
||
|
PJ_END;
|
||
|
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int exception_test(void)
|
||
|
{
|
||
|
int i, rc;
|
||
|
enum { LOOP = 10 };
|
||
|
|
||
|
for (i=0; i<LOOP; ++i) {
|
||
|
if ((rc=test()) != 0) {
|
||
|
PJ_LOG(3,("", "...failed at i=%d (rc=%d)", i, rc));
|
||
|
return rc;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
/* To prevent warning about "translation unit is empty"
|
||
|
* when this test is disabled.
|
||
|
*/
|
||
|
int dummy_exception_test;
|
||
|
#endif /* INCLUDE_EXCEPTION_TEST */
|
||
|
|
||
|
|