[svn-commits] rmudgett: branch rmudgett/q931_fsm r2248 - /team/rmudgett/q931_fsm/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Mar 10 12:28:41 CST 2011


Author: rmudgett
Date: Thu Mar 10 12:28:39 2011
New Revision: 2248

URL: http://svnview.digium.com/svn/libpri?view=rev&rev=2248
Log:
* Add test FSM statistics and checks if the statistics match expected
values.

* Minor tweaks to fsm_transition() usage.

Modified:
    team/rmudgett/q931_fsm/fsmtest.c
    team/rmudgett/q931_fsm/pri_fsm.c
    team/rmudgett/q931_fsm/pri_fsm.h

Modified: team/rmudgett/q931_fsm/fsmtest.c
URL: http://svnview.digium.com/svn/libpri/team/rmudgett/q931_fsm/fsmtest.c?view=diff&rev=2248&r1=2247&r2=2248
==============================================================================
--- team/rmudgett/q931_fsm/fsmtest.c (original)
+++ team/rmudgett/q931_fsm/fsmtest.c Thu Mar 10 12:28:39 2011
@@ -105,6 +105,60 @@
 	}
 }
 
+enum tst_state {
+	TST_S1,
+	TST_S1_1,
+	TST_S1_1_1,
+	TST_S1_1_2,
+	TST_S1_2,
+	TST_S1_3,
+	TST_S1_3_1,
+
+	TST_NUM_STATES
+};
+
+/*!
+ * \internal
+ * \brief Convert the given test FSM state to string.
+ *
+ * \param state Test FSM state to convert.
+ *
+ * \return String equivalent of event code.
+ */
+static const char *tst_state2str(enum tst_state state)
+{
+	switch (state) {
+	case TST_S1:
+		return "TST_S1";
+	case TST_S1_1:
+		return "TST_S1_1";
+	case TST_S1_1_1:
+		return "TST_S1_1_1";
+	case TST_S1_1_2:
+		return "TST_S1_1_2";
+	case TST_S1_2:
+		return "TST_S1_2";
+	case TST_S1_3:
+		return "TST_S1_3";
+	case TST_S1_3_1:
+		return "TST_S1_3_1";
+	case TST_NUM_STATES:
+		break;
+	}
+	return "TST_state_unknown";
+}
+
+struct tst_statistics {
+	struct {
+		/*! How many prolog events. */
+		int prolog;
+		/*! How many epilog events. */
+		int epilog;
+	} visit[TST_NUM_STATES];
+	/*! How many times the FSM was destroyed. */
+	int destroyed;
+};
+
 static void *tst_state_1(struct pri *ctrl, struct fsm_ctrl *fsm, struct fsm_event *event);
 static void *tst_state_1_1(struct pri *ctrl, struct fsm_ctrl *fsm, struct fsm_event *event);
 static void *tst_state_1_1_1(struct pri *ctrl, struct fsm_ctrl *fsm, struct fsm_event *event);
@@ -140,11 +194,13 @@
 		return FSM_IS_DEBUG(ctrl->debug & PRI_DEBUG_Q931_STATE);
 	case FSM_EV_PROLOG:
 		ACT_DEBUG(ctrl, fsm, event);
+		++((struct tst_statistics *) (fsm->parms))->visit[TST_S1_1_1].prolog;
 		break;
 	case FSM_EV_INIT:
 		return NULL;
 	case FSM_EV_EPILOG:
 		ACT_DEBUG(ctrl, fsm, event);
+		++((struct tst_statistics *) (fsm->parms))->visit[TST_S1_1_1].epilog;
 		break;
 	case TST_EV_A:
 		ACT_DEBUG(ctrl, fsm, event);
@@ -155,249 +211,254 @@
 		fsm_event_push(ctrl, fsm, TST_EV_D);
 		fsm_event_push(ctrl, fsm, TST_EV_C);
 		fsm_event_post(ctrl, fsm, TST_EV_E);
-		fsm_transition(ctrl, ctrl->debug & PRI_DEBUG_Q931_STATE, fsm, tst_state_1_1_1);
+		return fsm_transition(ctrl, ctrl->debug & PRI_DEBUG_Q931_STATE, fsm, tst_state_1_1_1);
+	case TST_EV_C:
+		ACT_DEBUG(ctrl, fsm, event);
+		return fsm_transition(ctrl, ctrl->debug & PRI_DEBUG_Q931_STATE, fsm, tst_state_1_1_2);
+	case TST_EV_E:
+		ACT_DEBUG(ctrl, fsm, event);
+		fsm_event_post(ctrl, fsm, TST_EV_F);
+		return fsm_transition(ctrl, ctrl->debug & PRI_DEBUG_Q931_STATE, fsm, tst_state_1_2);
+	default:
+		break;
+	}
+	return tst_state_1_1;
+}
+
+/*!
+ * \internal
+ * \brief State 1.1.2.
+ *
+ * \param ctrl D channel controller.
+ * \param event Event to process.
+ *
+ * \return The value has various meanings depending upon what
+ * event was passed in.
+ * \see enum fsm_ev event descriptions for return value.
+ */
+static void *tst_state_1_1_2(struct pri *ctrl, struct fsm_ctrl *fsm, struct fsm_event *event)
+{
+	switch (event->code) {
+	case FSM_EV_GET_SUPERSTATE:
+		return tst_state_1_1;
+	case FSM_EV_GET_STATE_NAME:
+		return (void *) __PRETTY_FUNCTION__;
+	case FSM_EV_GET_EV_NAME:
+		return (void *) tst_ev2str(event->parms.num);
+	case FSM_EV_GET_DEBUG:
+		return FSM_IS_DEBUG(ctrl->debug & PRI_DEBUG_Q931_STATE);
+	case FSM_EV_PROLOG:
+		ACT_DEBUG(ctrl, fsm, event);
+		++((struct tst_statistics *) (fsm->parms))->visit[TST_S1_1_2].prolog;
+		break;
+	case FSM_EV_INIT:
 		return NULL;
-	case TST_EV_C:
-		ACT_DEBUG(ctrl, fsm, event);
-		fsm_transition(ctrl, ctrl->debug & PRI_DEBUG_Q931_STATE, fsm, tst_state_1_1_2);
+	case FSM_EV_EPILOG:
+		ACT_DEBUG(ctrl, fsm, event);
+		++((struct tst_statistics *) (fsm->parms))->visit[TST_S1_1_2].epilog;
+		break;
+	case TST_EV_D:
+		ACT_DEBUG(ctrl, fsm, event);
+		return fsm_transition(ctrl, ctrl->debug & PRI_DEBUG_Q931_STATE, fsm, tst_state_1_1);
+	case TST_EV_H:
+		ACT_DEBUG(ctrl, fsm, event);
+		return fsm_transition(ctrl, ctrl->debug & PRI_DEBUG_Q931_STATE, fsm, NULL);
+	default:
+		break;
+	}
+	return tst_state_1_1;
+}
+
+/*!
+ * \internal
+ * \brief State 1.1.
+ *
+ * \param ctrl D channel controller.
+ * \param event Event to process.
+ *
+ * \return The value has various meanings depending upon what
+ * event was passed in.
+ * \see enum fsm_ev event descriptions for return value.
+ */
+static void *tst_state_1_1(struct pri *ctrl, struct fsm_ctrl *fsm, struct fsm_event *event)
+{
+	switch (event->code) {
+	case FSM_EV_GET_SUPERSTATE:
+		return tst_state_1;
+	case FSM_EV_GET_STATE_NAME:
+		return (void *) __PRETTY_FUNCTION__;
+	case FSM_EV_GET_EV_NAME:
+		return (void *) tst_ev2str(event->parms.num);
+	case FSM_EV_GET_DEBUG:
+		return FSM_IS_DEBUG(ctrl->debug & PRI_DEBUG_Q931_STATE);
+	case FSM_EV_PROLOG:
+		ACT_DEBUG(ctrl, fsm, event);
+		++((struct tst_statistics *) (fsm->parms))->visit[TST_S1_1].prolog;
+		break;
+	case FSM_EV_INIT:
+		return tst_state_1_1_1;
+	case FSM_EV_EPILOG:
+		ACT_DEBUG(ctrl, fsm, event);
+		++((struct tst_statistics *) (fsm->parms))->visit[TST_S1_1].epilog;
+		break;
+	default:
+		break;
+	}
+	return tst_state_1;
+}
+
+/*!
+ * \internal
+ * \brief State 1.2.
+ *
+ * \param ctrl D channel controller.
+ * \param event Event to process.
+ *
+ * \return The value has various meanings depending upon what
+ * event was passed in.
+ * \see enum fsm_ev event descriptions for return value.
+ */
+static void *tst_state_1_2(struct pri *ctrl, struct fsm_ctrl *fsm, struct fsm_event *event)
+{
+	switch (event->code) {
+	case FSM_EV_GET_SUPERSTATE:
+		return tst_state_1;
+	case FSM_EV_GET_STATE_NAME:
+		return (void *) __PRETTY_FUNCTION__;
+	case FSM_EV_GET_EV_NAME:
+		return (void *) tst_ev2str(event->parms.num);
+	case FSM_EV_GET_DEBUG:
+		return FSM_IS_DEBUG(ctrl->debug & PRI_DEBUG_Q931_STATE);
+	case FSM_EV_PROLOG:
+		ACT_DEBUG(ctrl, fsm, event);
+		++((struct tst_statistics *) (fsm->parms))->visit[TST_S1_2].prolog;
+		break;
+	case FSM_EV_INIT:
 		return NULL;
-	case TST_EV_E:
-		ACT_DEBUG(ctrl, fsm, event);
-		fsm_event_post(ctrl, fsm, TST_EV_F);
-		fsm_transition(ctrl, ctrl->debug & PRI_DEBUG_Q931_STATE, fsm, tst_state_1_2);
+	case FSM_EV_EPILOG:
+		ACT_DEBUG(ctrl, fsm, event);
+		++((struct tst_statistics *) (fsm->parms))->visit[TST_S1_2].epilog;
+		break;
+	case TST_EV_F:
+		ACT_DEBUG(ctrl, fsm, event);
+		fsm_event_post(ctrl, fsm, TST_EV_G);
+		return fsm_transition(ctrl, ctrl->debug & PRI_DEBUG_Q931_STATE, fsm, tst_state_1_3);
+	default:
+		break;
+	}
+	return tst_state_1;
+}
+
+/*!
+ * \internal
+ * \brief State 1.3.1.
+ *
+ * \param ctrl D channel controller.
+ * \param event Event to process.
+ *
+ * \return The value has various meanings depending upon what
+ * event was passed in.
+ * \see enum fsm_ev event descriptions for return value.
+ */
+static void *tst_state_1_3_1(struct pri *ctrl, struct fsm_ctrl *fsm, struct fsm_event *event)
+{
+	switch (event->code) {
+	case FSM_EV_GET_SUPERSTATE:
+		return tst_state_1_3;
+	case FSM_EV_GET_STATE_NAME:
+		return (void *) __PRETTY_FUNCTION__;
+	case FSM_EV_GET_EV_NAME:
+		return (void *) tst_ev2str(event->parms.num);
+	case FSM_EV_GET_DEBUG:
+		return FSM_IS_DEBUG(ctrl->debug & PRI_DEBUG_Q931_STATE);
+	case FSM_EV_PROLOG:
+		ACT_DEBUG(ctrl, fsm, event);
+		++((struct tst_statistics *) (fsm->parms))->visit[TST_S1_3_1].prolog;
+		break;
+	case FSM_EV_INIT:
 		return NULL;
-	default:
-		break;
-	}
-	return tst_state_1_1;
-}
-
-/*!
- * \internal
- * \brief State 1.1.2.
- *
- * \param ctrl D channel controller.
- * \param event Event to process.
- *
- * \return The value has various meanings depending upon what
- * event was passed in.
- * \see enum fsm_ev event descriptions for return value.
- */
-static void *tst_state_1_1_2(struct pri *ctrl, struct fsm_ctrl *fsm, struct fsm_event *event)
-{
-	switch (event->code) {
-	case FSM_EV_GET_SUPERSTATE:
+	case FSM_EV_EPILOG:
+		ACT_DEBUG(ctrl, fsm, event);
+		++((struct tst_statistics *) (fsm->parms))->visit[TST_S1_3_1].epilog;
+		break;
+	default:
+		break;
+	}
+	return tst_state_1_3;
+}
+
+/*!
+ * \internal
+ * \brief State 1.3.
+ *
+ * \param ctrl D channel controller.
+ * \param event Event to process.
+ *
+ * \return The value has various meanings depending upon what
+ * event was passed in.
+ * \see enum fsm_ev event descriptions for return value.
+ */
+static void *tst_state_1_3(struct pri *ctrl, struct fsm_ctrl *fsm, struct fsm_event *event)
+{
+	switch (event->code) {
+	case FSM_EV_GET_SUPERSTATE:
+		return tst_state_1;
+	case FSM_EV_GET_STATE_NAME:
+		return (void *) __PRETTY_FUNCTION__;
+	case FSM_EV_GET_EV_NAME:
+		return (void *) tst_ev2str(event->parms.num);
+	case FSM_EV_GET_DEBUG:
+		return FSM_IS_DEBUG(ctrl->debug & PRI_DEBUG_Q931_STATE);
+	case FSM_EV_PROLOG:
+		ACT_DEBUG(ctrl, fsm, event);
+		++((struct tst_statistics *) (fsm->parms))->visit[TST_S1_3].prolog;
+		break;
+	case FSM_EV_INIT:
+		return tst_state_1_3_1;
+	case FSM_EV_EPILOG:
+		ACT_DEBUG(ctrl, fsm, event);
+		++((struct tst_statistics *) (fsm->parms))->visit[TST_S1_3].epilog;
+		break;
+	case TST_EV_G:
+		ACT_DEBUG(ctrl, fsm, event);
+		return fsm_transition(ctrl, ctrl->debug & PRI_DEBUG_Q931_STATE, fsm, tst_state_1_1_2);
+	default:
+		break;
+	}
+	return tst_state_1;
+}
+
+/*!
+ * \internal
+ * \brief State 1.
+ *
+ * \param ctrl D channel controller.
+ * \param event Event to process.
+ *
+ * \return The value has various meanings depending upon what
+ * event was passed in.
+ * \see enum fsm_ev event descriptions for return value.
+ */
+static void *tst_state_1(struct pri *ctrl, struct fsm_ctrl *fsm, struct fsm_event *event)
+{
+	switch (event->code) {
+	case FSM_EV_GET_SUPERSTATE:
+		return fsm_top_state;
+	case FSM_EV_GET_STATE_NAME:
+		return (void *) __PRETTY_FUNCTION__;
+	case FSM_EV_GET_EV_NAME:
+		return (void *) tst_ev2str(event->parms.num);
+	case FSM_EV_GET_DEBUG:
+		return FSM_IS_DEBUG(ctrl->debug & PRI_DEBUG_Q931_STATE);
+	case FSM_EV_PROLOG:
+		ACT_DEBUG(ctrl, fsm, event);
+		++((struct tst_statistics *) (fsm->parms))->visit[TST_S1].prolog;
+		break;
+	case FSM_EV_INIT:
 		return tst_state_1_1;
-	case FSM_EV_GET_STATE_NAME:
-		return (void *) __PRETTY_FUNCTION__;
-	case FSM_EV_GET_EV_NAME:
-		return (void *) tst_ev2str(event->parms.num);
-	case FSM_EV_GET_DEBUG:
-		return FSM_IS_DEBUG(ctrl->debug & PRI_DEBUG_Q931_STATE);
-	case FSM_EV_PROLOG:
-		ACT_DEBUG(ctrl, fsm, event);
-		break;
-	case FSM_EV_INIT:
-		return NULL;
-	case FSM_EV_EPILOG:
-		ACT_DEBUG(ctrl, fsm, event);
-		break;
-	case TST_EV_D:
-		ACT_DEBUG(ctrl, fsm, event);
-		fsm_transition(ctrl, ctrl->debug & PRI_DEBUG_Q931_STATE, fsm, tst_state_1_1);
-		return NULL;
-	case TST_EV_H:
-		ACT_DEBUG(ctrl, fsm, event);
-		fsm_transition(ctrl, ctrl->debug & PRI_DEBUG_Q931_STATE, fsm, NULL);
-		return NULL;
-	default:
-		break;
-	}
-	return tst_state_1_1;
-}
-
-/*!
- * \internal
- * \brief State 1.1.
- *
- * \param ctrl D channel controller.
- * \param event Event to process.
- *
- * \return The value has various meanings depending upon what
- * event was passed in.
- * \see enum fsm_ev event descriptions for return value.
- */
-static void *tst_state_1_1(struct pri *ctrl, struct fsm_ctrl *fsm, struct fsm_event *event)
-{
-	switch (event->code) {
-	case FSM_EV_GET_SUPERSTATE:
-		return tst_state_1;
-	case FSM_EV_GET_STATE_NAME:
-		return (void *) __PRETTY_FUNCTION__;
-	case FSM_EV_GET_EV_NAME:
-		return (void *) tst_ev2str(event->parms.num);
-	case FSM_EV_GET_DEBUG:
-		return FSM_IS_DEBUG(ctrl->debug & PRI_DEBUG_Q931_STATE);
-	case FSM_EV_PROLOG:
-		ACT_DEBUG(ctrl, fsm, event);
-		break;
-	case FSM_EV_INIT:
-		return tst_state_1_1_1;
-	case FSM_EV_EPILOG:
-		ACT_DEBUG(ctrl, fsm, event);
-		break;
-	default:
-		break;
-	}
-	return tst_state_1;
-}
-
-/*!
- * \internal
- * \brief State 1.2.
- *
- * \param ctrl D channel controller.
- * \param event Event to process.
- *
- * \return The value has various meanings depending upon what
- * event was passed in.
- * \see enum fsm_ev event descriptions for return value.
- */
-static void *tst_state_1_2(struct pri *ctrl, struct fsm_ctrl *fsm, struct fsm_event *event)
-{
-	switch (event->code) {
-	case FSM_EV_GET_SUPERSTATE:
-		return tst_state_1;
-	case FSM_EV_GET_STATE_NAME:
-		return (void *) __PRETTY_FUNCTION__;
-	case FSM_EV_GET_EV_NAME:
-		return (void *) tst_ev2str(event->parms.num);
-	case FSM_EV_GET_DEBUG:
-		return FSM_IS_DEBUG(ctrl->debug & PRI_DEBUG_Q931_STATE);
-	case FSM_EV_PROLOG:
-		ACT_DEBUG(ctrl, fsm, event);
-		break;
-	case FSM_EV_INIT:
-		return NULL;
-	case FSM_EV_EPILOG:
-		ACT_DEBUG(ctrl, fsm, event);
-		break;
-	case TST_EV_F:
-		ACT_DEBUG(ctrl, fsm, event);
-		fsm_event_post(ctrl, fsm, TST_EV_G);
-		fsm_transition(ctrl, ctrl->debug & PRI_DEBUG_Q931_STATE, fsm, tst_state_1_3);
-		return NULL;
-	default:
-		break;
-	}
-	return tst_state_1;
-}
-
-/*!
- * \internal
- * \brief State 1.3.1.
- *
- * \param ctrl D channel controller.
- * \param event Event to process.
- *
- * \return The value has various meanings depending upon what
- * event was passed in.
- * \see enum fsm_ev event descriptions for return value.
- */
-static void *tst_state_1_3_1(struct pri *ctrl, struct fsm_ctrl *fsm, struct fsm_event *event)
-{
-	switch (event->code) {
-	case FSM_EV_GET_SUPERSTATE:
-		return tst_state_1_3;
-	case FSM_EV_GET_STATE_NAME:
-		return (void *) __PRETTY_FUNCTION__;
-	case FSM_EV_GET_EV_NAME:
-		return (void *) tst_ev2str(event->parms.num);
-	case FSM_EV_GET_DEBUG:
-		return FSM_IS_DEBUG(ctrl->debug & PRI_DEBUG_Q931_STATE);
-	case FSM_EV_PROLOG:
-		ACT_DEBUG(ctrl, fsm, event);
-		break;
-	case FSM_EV_INIT:
-		return NULL;
-	case FSM_EV_EPILOG:
-		ACT_DEBUG(ctrl, fsm, event);
-		break;
-	default:
-		break;
-	}
-	return tst_state_1_3;
-}
-
-/*!
- * \internal
- * \brief State 1.3.
- *
- * \param ctrl D channel controller.
- * \param event Event to process.
- *
- * \return The value has various meanings depending upon what
- * event was passed in.
- * \see enum fsm_ev event descriptions for return value.
- */
-static void *tst_state_1_3(struct pri *ctrl, struct fsm_ctrl *fsm, struct fsm_event *event)
-{
-	switch (event->code) {
-	case FSM_EV_GET_SUPERSTATE:
-		return tst_state_1;
-	case FSM_EV_GET_STATE_NAME:
-		return (void *) __PRETTY_FUNCTION__;
-	case FSM_EV_GET_EV_NAME:
-		return (void *) tst_ev2str(event->parms.num);
-	case FSM_EV_GET_DEBUG:
-		return FSM_IS_DEBUG(ctrl->debug & PRI_DEBUG_Q931_STATE);
-	case FSM_EV_PROLOG:
-		ACT_DEBUG(ctrl, fsm, event);
-		break;
-	case FSM_EV_INIT:
-		return tst_state_1_3_1;
-	case FSM_EV_EPILOG:
-		ACT_DEBUG(ctrl, fsm, event);
-		break;
-	case TST_EV_G:
-		ACT_DEBUG(ctrl, fsm, event);
-		fsm_transition(ctrl, ctrl->debug & PRI_DEBUG_Q931_STATE, fsm, tst_state_1_1_2);
-		return NULL;
-	default:
-		break;
-	}
-	return tst_state_1;
-}
-
-/*!
- * \internal
- * \brief State 1.
- *
- * \param ctrl D channel controller.
- * \param event Event to process.
- *
- * \return The value has various meanings depending upon what
- * event was passed in.
- * \see enum fsm_ev event descriptions for return value.
- */
-static void *tst_state_1(struct pri *ctrl, struct fsm_ctrl *fsm, struct fsm_event *event)
-{
-	switch (event->code) {
-	case FSM_EV_GET_SUPERSTATE:
-		return fsm_top_state;
-	case FSM_EV_GET_STATE_NAME:
-		return (void *) __PRETTY_FUNCTION__;
-	case FSM_EV_GET_EV_NAME:
-		return (void *) tst_ev2str(event->parms.num);
-	case FSM_EV_GET_DEBUG:
-		return FSM_IS_DEBUG(ctrl->debug & PRI_DEBUG_Q931_STATE);
-	case FSM_EV_PROLOG:
-		ACT_DEBUG(ctrl, fsm, event);
-		break;
-	case FSM_EV_INIT:
-		return tst_state_1_1;
-	case FSM_EV_EPILOG:
-		ACT_DEBUG(ctrl, fsm, event);
+	case FSM_EV_EPILOG:
+		ACT_DEBUG(ctrl, fsm, event);
+		++((struct tst_statistics *) (fsm->parms))->visit[TST_S1].epilog;
 		break;
 	default:
 		break;
@@ -416,8 +477,11 @@
  */
 static void tst_fsm_destructor(struct pri *ctrl, struct fsm_ctrl *fsm, void *parms)
 {
+	struct tst_statistics *stats;
+
 	pri_message(ctrl, DBGHEAD "\n", DBGINFO);
-	*(int *) parms = *((int *) parms) + 1;
+	stats = parms;
+	++stats->destroyed;
 }
 
 /*!
@@ -434,7 +498,19 @@
 	static struct pri dummy_ctrl;
 	static struct fsm_queue ev_q;
 	static struct fsm_ctrl fsm;
-	static int fsm_destroyed;
+	static struct tst_statistics tst_stats;
+
+	static const int expected_visits[TST_NUM_STATES] = {
+		[TST_S1] = 1,
+		[TST_S1_1] = 2,
+		[TST_S1_1_1] = 3,
+		[TST_S1_1_2] = 2,
+		[TST_S1_2] = 1,
+		[TST_S1_3] = 1,
+		[TST_S1_3_1] = 1,
+	};
+
+	int idx;
 
 	pri_set_message(tst_pri_message);
 	pri_set_error(tst_pri_error);
@@ -448,9 +524,9 @@
 	/* Setup FSM */
 	fsm.state = NULL;
 	fsm.destructor = tst_fsm_destructor;
-	fsm.name = "Test FSM";
+	fsm.name = "Test";
 	fsm.que = &ev_q;
-	fsm.parms = &fsm_destroyed;
+	fsm.parms = &tst_stats;
 	fsm_init(&dummy_ctrl, &fsm, tst_state_1);
 
 	/* Nothing to do. */
@@ -464,8 +540,27 @@
 	fsm_event_post(&dummy_ctrl, &fsm, TST_EV_H);
 	fsm_run(&dummy_ctrl, &ev_q);
 
-	if (fsm_destroyed != 1) {
-		pri_error(&dummy_ctrl, "Test FSM destroyed %d times!\n", fsm_destroyed);
+	/* Display FSM state statistics. */
+	for (idx = 0; idx < ARRAY_LEN(tst_stats.visit); ++idx) {
+		pri_message(&dummy_ctrl, "State %-10s: prologs: %d epilogs: %d\n",
+			tst_state2str(idx),
+			tst_stats.visit[idx].prolog, tst_stats.visit[idx].epilog);
+	}
+
+	/* Check FSM state statistics. */
+	for (idx = 0; idx < ARRAY_LEN(tst_stats.visit); ++idx) {
+		if (tst_stats.visit[idx].prolog != tst_stats.visit[idx].epilog) {
+			pri_error(&dummy_ctrl, "State %s: Prologs do not match epilogs!\n",
+				tst_state2str(idx));
+		}
+		if (tst_stats.visit[idx].prolog != expected_visits[idx]) {
+			pri_error(&dummy_ctrl,
+				"State %s: Did not get the expected number of visits!\n",
+				tst_state2str(idx));
+		}
+	}
+	if (tst_stats.destroyed != 1) {
+		pri_error(&dummy_ctrl, "%s: FSM destroyed %d times!\n", fsm.name, tst_stats.destroyed);
 	}
 
 	return 0;

Modified: team/rmudgett/q931_fsm/pri_fsm.c
URL: http://svnview.digium.com/svn/libpri/team/rmudgett/q931_fsm/pri_fsm.c?view=diff&rev=2248&r1=2247&r2=2248
==============================================================================
--- team/rmudgett/q931_fsm/pri_fsm.c (original)
+++ team/rmudgett/q931_fsm/pri_fsm.c Thu Mar 10 12:28:39 2011
@@ -242,9 +242,11 @@
  * \param fsm FSM that is transitioning states.
  * \param dest Transitioning to state. (NULL if terminal)
  *
- * \return Nothing
- */
-void fsm_transition(struct pri *ctrl, int debug, struct fsm_ctrl *fsm, fsm_state dest)
+ * \return NULL to encourage the use of "return
+ * fsm_transition();".  The expression emphasizes the fact that
+ * the state has completed processing an event.
+ */
+void *fsm_transition(struct pri *ctrl, int debug, struct fsm_ctrl *fsm, fsm_state dest)
 {
 	struct fsm_event local_event;
 	fsm_state epilog_state[FSM_MAX_SUPERSTATE_NESTING + 1];/* Plus top state. */
@@ -261,7 +263,7 @@
 
 	src = fsm->state;
 	if (!src || src == fsm_top_state) {
-		/* This is the initial transition to start the FSM. */
+		/* This is the initial event transition to start the FSM. */
 		fsm->state = fsm_top_state;
 		src = NULL;
 	}
@@ -271,7 +273,7 @@
 	if (dest && dest != fsm_top_state) {
 		dest_name = dest(ctrl, fsm, &local_event);
 	} else {
-		/* This is the terminal transition to end the FSM. */
+		/* This is the terminal event transition to end the FSM. */
 		dest_name = fsm_top_state(ctrl, fsm, &local_event);
 		dest = NULL;
 	}
@@ -292,7 +294,7 @@
 
 			pri_error(ctrl, "%s: FSM source state %s nested too deep!\n", fsm->name,
 				src_name);
-			return;
+			return NULL;
 		}
 		src = src(ctrl, fsm, &local_event);
 		if (src == fsm_top_state) {
@@ -308,7 +310,7 @@
 		if (FSM_MAX_SUPERSTATE_NESTING <= prolog_index) {
 			pri_error(ctrl, "%s: FSM destination state %s nested too deep!\n", fsm->name,
 				dest_name);
-			return;
+			return NULL;
 		}
 		dest = dest(ctrl, fsm, &local_event);
 		if (dest == fsm_top_state) {
@@ -320,7 +322,7 @@
 	if (!epilog_index && !prolog_index) {
 		pri_error(ctrl, "%s: FSM initial transition is termination transition!\n",
 			fsm->name);
-		return;
+		return NULL;
 	}
 
 	/* Find first non-common superstate level. */
@@ -382,13 +384,13 @@
 	} else {
 		/* Termination transition. */
 		fsm->state = fsm_top_state;
+		if (debug) {
+			pri_message(ctrl, "%s: Terminated\n", fsm->name);
+		}
 		if (fsm->destructor) {
-			if (debug) {
-				pri_message(ctrl, "%s: Destroying\n", fsm->name);
-			}
 			fsm->destructor(ctrl, fsm, fsm->parms);
 		}
-		return;
+		return NULL;
 	}
 
 	/* We reached the specified destination state. */
@@ -421,6 +423,8 @@
 		/* We drilled one level deeper. */
 		fsm->state = dest;
 	}
+
+	return NULL;
 }
 
 /*!
@@ -494,7 +498,7 @@
 }
 
 /*!
- * \brief Do the initial transition to start the FSM.
+ * \brief Do the initial event transition to start the FSM.
  *
  * \param ctrl D channel controller.
  * \param fsm Filled in FSM control structure set to the initial FSM state.
@@ -515,7 +519,7 @@
 	}
 
 	if (debug) {
-		pri_message(ctrl, "%s: Initial transition\n", fsm->name);
+		pri_message(ctrl, "%s: Initial event\n", fsm->name);
 	}
 	fsm->state = fsm_top_state;
 	fsm_transition(ctrl, debug, fsm, init);

Modified: team/rmudgett/q931_fsm/pri_fsm.h
URL: http://svnview.digium.com/svn/libpri/team/rmudgett/q931_fsm/pri_fsm.h?view=diff&rev=2248&r1=2247&r2=2248
==============================================================================
--- team/rmudgett/q931_fsm/pri_fsm.h (original)
+++ team/rmudgett/q931_fsm/pri_fsm.h Thu Mar 10 12:28:39 2011
@@ -211,7 +211,7 @@
 void fsm_event_push(struct pri *ctrl, struct fsm_ctrl *fsm, int code);
 void fsm_event_post(struct pri *ctrl, struct fsm_ctrl *fsm, int code);
 void *fsm_top_state(struct pri *ctrl, struct fsm_ctrl *fsm, struct fsm_event *event);
-void fsm_transition(struct pri *ctrl, int debug, struct fsm_ctrl *fsm, fsm_state dest);
+void *fsm_transition(struct pri *ctrl, int debug, struct fsm_ctrl *fsm, fsm_state dest);
 void fsm_run(struct pri *ctrl, struct fsm_queue *que);
 void fsm_init(struct pri *ctrl, struct fsm_ctrl *fsm, fsm_state init);
 




More information about the svn-commits mailing list