0e11b868362517491b9f14352a7e227d2cb1ac97
[silc.git] / lib / silcutil / tests / test_silcasync.c
1 /* SilcAsyncOperation tests */
2
3 #include "silcincludes.h"
4 #include "silcfsm.h"
5 #include "silcasync.h"
6
7 typedef void (*Callback)(void *context);
8
9 SilcSchedule schedule;
10
11 typedef struct {
12   SilcFSM fsm;
13   SilcFSMSemaStruct sema;
14   SilcAsyncOperation op;
15   Callback cb;
16   void *cb_context;
17   SilcBool aborted;
18 } *Foo;
19
20 SILC_FSM_STATE(test_st_start);
21 SILC_FSM_STATE(test_st_second);
22 SILC_FSM_STATE(test_st_finish);
23
24 SILC_TASK_CALLBACK(async_call_timeout)
25 {
26   Foo f = context;
27   SILC_LOG_DEBUG(("******Async call cb, continuing FSM"));
28   silc_async_free(f->op);
29   f->cb(f->cb_context);
30 }
31
32 static void async_abort(SilcAsyncOperation op, void *context)
33 {
34   Foo f = context;
35   SILC_LOG_DEBUG(("Async operation aborted"));
36   silc_schedule_task_del_by_context(schedule, f);
37   silc_schedule_task_del_by_callback(schedule, async_call_timeout);
38   f->aborted = TRUE;
39 }
40
41 static SilcAsyncOperation async_call(Callback cb, void *context)
42 {
43   Foo f = context;
44
45   SILC_LOG_DEBUG(("Async call"));
46
47   f->cb = cb;
48   f->cb_context = context;
49   f->op = silc_async_alloc(async_abort, NULL, f);
50
51   silc_schedule_task_add(schedule, 0, async_call_timeout, f, 2, 1,
52                          SILC_TASK_TIMEOUT);
53
54   return f->op;
55 }
56
57 static void async_call_cb(void *context)
58 {
59   Foo f = context;
60   SILC_LOG_DEBUG(("*******Callback, signal and continue to next state"));
61   f->op = NULL;
62   SILC_FSM_SEMA_POST(&f->sema);
63   SILC_FSM_CALL_CONTINUE(f->fsm);
64 }
65
66 SILC_FSM_STATE(test_st_start)
67 {
68   Foo f = fsm_context;
69
70   SILC_LOG_DEBUG(("test_st_start"));
71
72   silc_fsm_sema_init(&f->sema, fsm, 0);
73
74   /** Wait async callback */
75   SILC_LOG_DEBUG(("Call async call"));
76   silc_fsm_next_later(fsm, test_st_second, 1, 0);
77   SILC_FSM_CALL((f->op = async_call(async_call_cb, f)));
78 }
79
80 SILC_FSM_STATE(test_st_second)
81 {
82   Foo f = fsm_context;
83
84   SILC_LOG_DEBUG(("test_st_second"));
85
86   SILC_FSM_SEMA_TIMEDWAIT(&f->sema, 0, 1);
87
88   SILC_LOG_DEBUG(("Sema timedout, aborting async operation"));
89   if (f->op)
90     silc_async_abort(f->op, NULL, NULL);
91
92   /** Finish */
93   silc_fsm_next_later(fsm, test_st_finish, 2, 0);
94   return SILC_FSM_WAIT;
95 }
96
97 SILC_FSM_STATE(test_st_finish)
98 {
99   SILC_LOG_DEBUG(("test_st_finish"));
100
101   SILC_LOG_DEBUG(("Finish machine"));
102   return SILC_FSM_FINISH;
103 }
104
105 static void destructor(SilcFSM fsm, void *fsm_context,
106                        void *destructor_context)
107 {
108   SILC_LOG_DEBUG(("FSM destructor, stopping scheduler"));
109   silc_fsm_free(fsm);
110   silc_schedule_stop(schedule);
111 }
112
113 int main(int argc, char **argv)
114 {
115   SilcBool success = FALSE;
116   SilcFSM fsm;
117   Foo f;
118
119   if (argc > 1 && !strcmp(argv[1], "-d")) {
120     silc_log_debug(TRUE);
121     silc_log_debug_hexdump(TRUE);
122     silc_log_set_debug_string("*async*");
123   }
124
125   SILC_LOG_DEBUG(("Allocating scheduler"));
126   schedule = silc_schedule_init(0, NULL);
127
128   f = silc_calloc(1, sizeof(*f));
129   if (!f)
130     goto err;
131
132   SILC_LOG_DEBUG(("Allocating FSM context"));
133   fsm = silc_fsm_alloc(f, destructor, NULL, schedule);
134   if (!fsm)
135     goto err;
136   silc_fsm_start(fsm, test_st_start);
137   f->fsm = fsm;
138
139   SILC_LOG_DEBUG(("Running scheduler"));
140   silc_schedule(schedule);
141
142   if (!f->aborted)
143     goto err;
144
145   silc_schedule_uninit(schedule);
146   silc_free(f);
147
148   success = TRUE;
149
150  err:
151   SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
152   fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
153
154   return success;
155 }