Initial code commit for Toolkit 1.1.
[silc.git] / lib / silcutil / tests / test_silcasync.c
diff --git a/lib/silcutil/tests/test_silcasync.c b/lib/silcutil/tests/test_silcasync.c
new file mode 100644 (file)
index 0000000..836daec
--- /dev/null
@@ -0,0 +1,155 @@
+/* SilcAsyncOperation tests */
+
+#include "silcincludes.h"
+#include "silcfsm.h"
+#include "silcasync.h"
+
+typedef void (*Callback)(void *context);
+
+SilcSchedule schedule;
+
+typedef struct {
+  SilcFSM fsm;
+  SilcFSMSemaStruct sema;
+  SilcAsyncOperation op;
+  Callback cb;
+  void *cb_context;
+  bool aborted;
+} *Foo;
+
+SILC_FSM_STATE(test_st_start);
+SILC_FSM_STATE(test_st_second);
+SILC_FSM_STATE(test_st_finish);
+
+SILC_TASK_CALLBACK(async_call_timeout)
+{
+  Foo f = context;
+  SILC_LOG_DEBUG(("******Async call cb, continuing FSM"));
+  silc_async_free(f->op);
+  f->cb(f->cb_context);
+}
+
+static void async_abort(SilcAsyncOperation op, void *context)
+{
+  Foo f = context;
+  SILC_LOG_DEBUG(("Async operation aborted"));
+  silc_schedule_task_del_by_context(schedule, f);
+  silc_schedule_task_del_by_callback(schedule, async_call_timeout);
+  f->aborted = TRUE;
+}
+
+static SilcAsyncOperation async_call(Callback cb, void *context)
+{
+  Foo f = context;
+
+  SILC_LOG_DEBUG(("Async call"));
+
+  f->cb = cb;
+  f->cb_context = context;
+  f->op = silc_async_alloc(async_abort, NULL, f);
+
+  silc_schedule_task_add(schedule, 0, async_call_timeout, f, 2, 1,
+                        SILC_TASK_TIMEOUT);
+
+  return f->op;
+}
+
+static void async_call_cb(void *context)
+{
+  Foo f = context;
+  SILC_LOG_DEBUG(("*******Callback, signal and continue to next state"));
+  f->op = NULL;
+  SILC_FSM_SEMA_POST(&f->sema);
+  SILC_FSM_CALL_CONTINUE(f->fsm);
+}
+
+SILC_FSM_STATE(test_st_start)
+{
+  Foo f = fsm_context;
+
+  SILC_LOG_DEBUG(("test_st_start"));
+
+  silc_fsm_sema_init(&f->sema, fsm, 0);
+
+  /** Wait async callback */
+  SILC_LOG_DEBUG(("Call async call"));
+  silc_fsm_next_later(fsm, test_st_second, 1, 0);
+  SILC_FSM_CALL((f->op = async_call(async_call_cb, f)));
+}
+
+SILC_FSM_STATE(test_st_second)
+{
+  Foo f = fsm_context;
+
+  SILC_LOG_DEBUG(("test_st_second"));
+
+  SILC_FSM_SEMA_TIMEDWAIT(&f->sema, 0, 1);
+
+  SILC_LOG_DEBUG(("Sema timedout, aborting async operation"));
+  if (f->op)
+    silc_async_abort(f->op, NULL, NULL);
+
+  /** Finish */
+  silc_fsm_next_later(fsm, test_st_finish, 2, 0);
+  return SILC_FSM_WAIT;
+}
+
+SILC_FSM_STATE(test_st_finish)
+{
+  SILC_LOG_DEBUG(("test_st_finish"));
+
+  SILC_LOG_DEBUG(("Finish machine"));
+  return SILC_FSM_FINISH;
+}
+
+static void destructor(SilcFSM fsm, void *fsm_context,
+                      void *destructor_context)
+{
+  SILC_LOG_DEBUG(("FSM destructor, stopping scheduler"));
+  silc_fsm_free(fsm);
+  silc_schedule_stop(schedule);
+}
+
+int main(int argc, char **argv)
+{
+  bool success = FALSE;
+  SilcFSM fsm;
+  Foo f;
+
+  if (argc > 1 && !strcmp(argv[1], "-d")) {
+    silc_log_debug(TRUE);
+    silc_log_debug_hexdump(TRUE);
+    silc_log_set_debug_string("*async*");
+  }
+
+  SILC_LOG_DEBUG(("Allocating scheduler"));
+  schedule = silc_schedule_init(0, NULL);
+
+  f = silc_calloc(1, sizeof(*f));
+  if (!f)
+    goto err;
+
+  SILC_LOG_DEBUG(("Allocating FSM context"));
+  fsm = silc_fsm_alloc(f, destructor, NULL, schedule);
+  if (!fsm)
+    goto err;
+  silc_fsm_start(fsm, test_st_start);
+  f->fsm = fsm;
+
+  SILC_LOG_DEBUG(("Running scheduler"));
+  silc_schedule(schedule);
+
+  if (!f->aborted)
+    goto err;
+
+  silc_schedule_uninit(schedule);
+  silc_free(f);
+
+  success = TRUE;
+
+ err:
+  SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
+  fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
+
+  return success;
+}