<p>Harald Welte <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/9389">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Harald Welte: Looks good to me, approved
Jenkins Builder: Verified
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">add osmo_fsm_inst_state_chg_keep_timer()<br><br>Change-Id: I3c0e53b846b2208bd201ace99777f2286ea39ae8<br>---<br>M include/osmocom/core/fsm.h<br>M src/fsm.c<br>M tests/fsm/fsm_test.c<br>M tests/fsm/fsm_test.err<br>4 files changed, 188 insertions(+), 35 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/core/fsm.h b/include/osmocom/core/fsm.h</span><br><span>index 174396a..67e00ad 100644</span><br><span>--- a/include/osmocom/core/fsm.h</span><br><span>+++ b/include/osmocom/core/fsm.h</span><br><span>@@ -182,6 +182,21 @@</span><br><span> unsigned long timeout_secs, int T,</span><br><span> const char *file, int line);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! perform a state change while keeping the current timer running.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This is useful to keep a timeout across several states (without having to round the</span><br><span style="color: hsl(120, 100%, 40%);">+ * remaining time to seconds).</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This is a macro that calls _osmo_fsm_inst_state_chg_keep_timer() with the given</span><br><span style="color: hsl(120, 100%, 40%);">+ * parameters as well as the caller's source file and line number for logging</span><br><span style="color: hsl(120, 100%, 40%);">+ * purposes. See there for documentation.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#define osmo_fsm_inst_state_chg_keep_timer(fi, new_state) \</span><br><span style="color: hsl(120, 100%, 40%);">+ _osmo_fsm_inst_state_chg_keep_timer(fi, new_state, \</span><br><span style="color: hsl(120, 100%, 40%);">+ __BASE_FILE__, __LINE__)</span><br><span style="color: hsl(120, 100%, 40%);">+int _osmo_fsm_inst_state_chg_keep_timer(struct osmo_fsm_inst *fi, uint32_t new_state,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *file, int line);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! dispatch an event to an osmocom finite state machine instance</span><br><span> *</span><br><span> * This is a macro that calls _osmo_fsm_inst_dispatch() with the given</span><br><span>diff --git a/src/fsm.c b/src/fsm.c</span><br><span>index 0370f65..b5af2e7 100644</span><br><span>--- a/src/fsm.c</span><br><span>+++ b/src/fsm.c</span><br><span>@@ -429,15 +429,56 @@</span><br><span> return fsm->states[state].name;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int state_chg(struct osmo_fsm_inst *fi, uint32_t new_state,</span><br><span style="color: hsl(120, 100%, 40%);">+ bool keep_timer, unsigned long timeout_secs, int T,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *file, int line)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_fsm *fsm = fi->fsm;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t old_state = fi->state;</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct osmo_fsm_state *st = &fsm->states[fi->state];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* validate if new_state is a valid state */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!(st->out_state_mask & (1 << new_state))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPFSMLSRC(fi, LOGL_ERROR, file, line,</span><br><span style="color: hsl(120, 100%, 40%);">+ "transition to state %s not permitted!\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_state_name(fsm, new_state));</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EPERM;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!keep_timer) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* delete the old timer */</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_timer_del(&fi->timer);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (st->onleave)</span><br><span style="color: hsl(120, 100%, 40%);">+ st->onleave(fi, new_state);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGPFSMSRC(fi, file, line, "state_chg to %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_state_name(fsm, new_state));</span><br><span style="color: hsl(120, 100%, 40%);">+ fi->state = new_state;</span><br><span style="color: hsl(120, 100%, 40%);">+ st = &fsm->states[new_state];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!keep_timer && timeout_secs) {</span><br><span style="color: hsl(120, 100%, 40%);">+ fi->T = T;</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_timer_schedule(&fi->timer, timeout_secs, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Call 'onenter' last, user might terminate FSM from there */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (st->onenter)</span><br><span style="color: hsl(120, 100%, 40%);">+ st->onenter(fi, old_state);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! perform a state change of the given FSM instance</span><br><span> *</span><br><span> * Best invoke via the osmo_fsm_inst_state_chg() macro which logs the source</span><br><span> * file where the state change was effected. Alternatively, you may pass \a</span><br><span> * file as NULL to use the normal file/line indication instead.</span><br><span> *</span><br><span style="color: hsl(0, 100%, 40%);">- * All changes to the FSM instance state must be made via this</span><br><span style="color: hsl(120, 100%, 40%);">+ * All changes to the FSM instance state must be made via an osmo_fsm_inst_state_chg_*</span><br><span> * function. It verifies that the existing state actually permits a</span><br><span style="color: hsl(0, 100%, 40%);">- * transiiton to new_state.</span><br><span style="color: hsl(120, 100%, 40%);">+ * transition to new_state.</span><br><span> *</span><br><span> * timeout_secs and T are optional parameters, and only have any effect</span><br><span> * if timeout_secs is not 0. If the timeout function is used, then the</span><br><span>@@ -457,39 +498,32 @@</span><br><span> unsigned long timeout_secs, int T,</span><br><span> const char *file, int line)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct osmo_fsm *fsm = fi->fsm;</span><br><span style="color: hsl(0, 100%, 40%);">- uint32_t old_state = fi->state;</span><br><span style="color: hsl(0, 100%, 40%);">- const struct osmo_fsm_state *st = &fsm->states[fi->state];</span><br><span style="color: hsl(120, 100%, 40%);">+ return state_chg(fi, new_state, false, timeout_secs, T, file, line);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* validate if new_state is a valid state */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!(st->out_state_mask & (1 << new_state))) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPFSMLSRC(fi, LOGL_ERROR, file, line,</span><br><span style="color: hsl(0, 100%, 40%);">- "transition to state %s not permitted!\n",</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_fsm_state_name(fsm, new_state));</span><br><span style="color: hsl(0, 100%, 40%);">- return -EPERM;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* delete the old timer */</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_timer_del(&fi->timer);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (st->onleave)</span><br><span style="color: hsl(0, 100%, 40%);">- st->onleave(fi, new_state);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPFSMSRC(fi, file, line, "state_chg to %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_fsm_state_name(fsm, new_state));</span><br><span style="color: hsl(0, 100%, 40%);">- fi->state = new_state;</span><br><span style="color: hsl(0, 100%, 40%);">- st = &fsm->states[new_state];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (timeout_secs) {</span><br><span style="color: hsl(0, 100%, 40%);">- fi->T = T;</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_timer_schedule(&fi->timer, timeout_secs, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Call 'onenter' last, user might terminate FSM from there */</span><br><span style="color: hsl(0, 100%, 40%);">- if (st->onenter)</span><br><span style="color: hsl(0, 100%, 40%);">- st->onenter(fi, old_state);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+/*! perform a state change while keeping the current timer running.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This is useful to keep a timeout across several states (without having to round the</span><br><span style="color: hsl(120, 100%, 40%);">+ * remaining time to seconds).</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Best invoke via the osmo_fsm_inst_state_chg_keep_timer() macro which logs the source</span><br><span style="color: hsl(120, 100%, 40%);">+ * file where the state change was effected. Alternatively, you may pass \a</span><br><span style="color: hsl(120, 100%, 40%);">+ * file as NULL to use the normal file/line indication instead.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * All changes to the FSM instance state must be made via an osmo_fsm_inst_state_chg_*</span><br><span style="color: hsl(120, 100%, 40%);">+ * function. It verifies that the existing state actually permits a</span><br><span style="color: hsl(120, 100%, 40%);">+ * transition to new_state.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] fi FSM instance whose state is to change</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] new_state The new state into which we should change</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] file Calling source file (from osmo_fsm_inst_state_chg macro)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] line Calling source line (from osmo_fsm_inst_state_chg macro)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns 0 on success; negative on error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int _osmo_fsm_inst_state_chg_keep_timer(struct osmo_fsm_inst *fi, uint32_t new_state,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *file, int line)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return state_chg(fi, new_state, true, 0, 0, file, line);</span><br><span> }</span><br><span> </span><br><span> /*! dispatch an event to an osmocom finite state machine instance</span><br><span>diff --git a/tests/fsm/fsm_test.c b/tests/fsm/fsm_test.c</span><br><span>index e34164c..34a8399 100644</span><br><span>--- a/tests/fsm/fsm_test.c</span><br><span>+++ b/tests/fsm/fsm_test.c</span><br><span>@@ -266,6 +266,89 @@</span><br><span> osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REQUEST, NULL);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+const struct timeval fake_time_start_time = { 123, 456 };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define fake_time_passes(secs, usecs) do \</span><br><span style="color: hsl(120, 100%, 40%);">+{ \</span><br><span style="color: hsl(120, 100%, 40%);">+ struct timeval diff; \</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_gettimeofday_override_add(secs, usecs); \</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_clock_override_add(CLOCK_MONOTONIC, secs, usecs * 1000); \</span><br><span style="color: hsl(120, 100%, 40%);">+ timersub(&osmo_gettimeofday_override_time, &fake_time_start_time, &diff); \</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "Total time passed: %d.%06d s\n", \</span><br><span style="color: hsl(120, 100%, 40%);">+ (int)diff.tv_sec, (int)diff.tv_usec); \</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_timers_prepare(); \</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_timers_update(); \</span><br><span style="color: hsl(120, 100%, 40%);">+} while (0)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void fake_time_start()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct timespec *clock_override;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_gettimeofday_override_time = fake_time_start_time;</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_gettimeofday_override = true;</span><br><span style="color: hsl(120, 100%, 40%);">+ clock_override = osmo_clock_override_gettimespec(CLOCK_MONOTONIC);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(clock_override);</span><br><span style="color: hsl(120, 100%, 40%);">+ clock_override->tv_sec = fake_time_start_time.tv_sec;</span><br><span style="color: hsl(120, 100%, 40%);">+ clock_override->tv_nsec = fake_time_start_time.tv_usec * 1000;</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_clock_override_enable(CLOCK_MONOTONIC, true);</span><br><span style="color: hsl(120, 100%, 40%);">+ fake_time_passes(0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int timeout_fired = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+static int timer_cb(struct osmo_fsm_inst *fi)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ timeout_fired = fi->T;</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void test_state_chg_keep_timer()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_fsm_inst *fi;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "\n--- %s()\n", __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fsm.timer_cb = timer_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Test that no timer remains no timer */</span><br><span style="color: hsl(120, 100%, 40%);">+ fi = osmo_fsm_inst_alloc(&fsm, g_ctx, NULL, LOGL_DEBUG, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(fi);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_state_chg(fi, ST_ONE, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ timeout_fired = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_state_chg_keep_timer(fi, ST_TWO);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(timeout_fired == -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(fi->T == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REQUEST, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Test that a set time continues with exact precision */</span><br><span style="color: hsl(120, 100%, 40%);">+ fake_time_start();</span><br><span style="color: hsl(120, 100%, 40%);">+ fi = osmo_fsm_inst_alloc(&fsm, g_ctx, NULL, LOGL_DEBUG, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(fi);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_state_chg(fi, ST_ONE, 10, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ timeout_fired = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fake_time_passes(2, 342);</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_state_chg_keep_timer(fi, ST_TWO);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fake_time_passes(0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(timeout_fired == -1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fake_time_passes(7, 1000000 - 342 - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(timeout_fired == -1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fake_time_passes(0, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(timeout_fired == 10);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REQUEST, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "--- %s() done\n", __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static const struct log_info_cat default_categories[] = {</span><br><span> [DMAIN] = {</span><br><span> .name = "DMAIN",</span><br><span>@@ -306,6 +389,7 @@</span><br><span> osmo_fsm_inst_free(finst);</span><br><span> </span><br><span> test_id_api();</span><br><span style="color: hsl(120, 100%, 40%);">+ test_state_chg_keep_timer();</span><br><span> </span><br><span> osmo_fsm_unregister(&fsm);</span><br><span> exit(0);</span><br><span>diff --git a/tests/fsm/fsm_test.err b/tests/fsm/fsm_test.err</span><br><span>index 3237def..85606e2 100644</span><br><span>--- a/tests/fsm/fsm_test.err</span><br><span>+++ b/tests/fsm/fsm_test.err</span><br><span>@@ -80,4 +80,24 @@</span><br><span> Test_FSM(arbitrary_id){NULL}: Terminating (cause = OSMO_FSM_TERM_REQUEST)</span><br><span> [0;mTest_FSM(arbitrary_id){NULL}: Freeing instance</span><br><span> [0;mTest_FSM(arbitrary_id){NULL}: Deallocated</span><br><span style="color: hsl(0, 100%, 40%);">-[0;m</span><br><span>\ No newline at end of file</span><br><span style="color: hsl(120, 100%, 40%);">+[0;m</span><br><span style="color: hsl(120, 100%, 40%);">+--- test_state_chg_keep_timer()</span><br><span style="color: hsl(120, 100%, 40%);">+Test_FSM{NULL}: Allocated</span><br><span style="color: hsl(120, 100%, 40%);">+[0;mTest_FSM{NULL}: state_chg to ONE</span><br><span style="color: hsl(120, 100%, 40%);">+[0;mTest_FSM{ONE}: state_chg to TWO</span><br><span style="color: hsl(120, 100%, 40%);">+[0;mTest_FSM{TWO}: Terminating (cause = OSMO_FSM_TERM_REQUEST)</span><br><span style="color: hsl(120, 100%, 40%);">+[0;mTest_FSM{TWO}: Freeing instance</span><br><span style="color: hsl(120, 100%, 40%);">+[0;mTest_FSM{TWO}: Deallocated</span><br><span style="color: hsl(120, 100%, 40%);">+[0;mTotal time passed: 0.000000 s</span><br><span style="color: hsl(120, 100%, 40%);">+Test_FSM{NULL}: Allocated</span><br><span style="color: hsl(120, 100%, 40%);">+[0;mTest_FSM{NULL}: state_chg to ONE</span><br><span style="color: hsl(120, 100%, 40%);">+[0;mTotal time passed: 2.000342 s</span><br><span style="color: hsl(120, 100%, 40%);">+Test_FSM{ONE}: state_chg to TWO</span><br><span style="color: hsl(120, 100%, 40%);">+[0;mTotal time passed: 2.000342 s</span><br><span style="color: hsl(120, 100%, 40%);">+Total time passed: 9.999999 s</span><br><span style="color: hsl(120, 100%, 40%);">+Total time passed: 10.000000 s</span><br><span style="color: hsl(120, 100%, 40%);">+Test_FSM{TWO}: Timeout of T10</span><br><span style="color: hsl(120, 100%, 40%);">+[0;mTest_FSM{TWO}: Terminating (cause = OSMO_FSM_TERM_REQUEST)</span><br><span style="color: hsl(120, 100%, 40%);">+[0;mTest_FSM{TWO}: Freeing instance</span><br><span style="color: hsl(120, 100%, 40%);">+[0;mTest_FSM{TWO}: Deallocated</span><br><span style="color: hsl(120, 100%, 40%);">+[0;m--- test_state_chg_keep_timer() done</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/9389">change 9389</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/9389"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I3c0e53b846b2208bd201ace99777f2286ea39ae8 </div>
<div style="display:none"> Gerrit-Change-Number: 9389 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: Neels Hofmeyr <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>