Added SILC Server library.
[silc.git] / lib / silcutil / tests / test_silcasync.c
1 /* SilcAsyncOperation tests */
2
3 #include "silc.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   SilcBool timedout;
84
85   SILC_LOG_DEBUG(("test_st_second"));
86
87   SILC_FSM_SEMA_TIMEDWAIT(&f->sema, 0, 1, &timedout);
88
89   if (timedout == TRUE) {
90     SILC_LOG_DEBUG(("Sema timedout, aborting async operation"));
91     if (f->op)
92       silc_async_abort(f->op, NULL, NULL);
93   }
94
95   /** Finish */
96   silc_fsm_next_later(fsm, test_st_finish, 2, 0);
97   return SILC_FSM_WAIT;
98 }
99
100 SILC_FSM_STATE(test_st_finish)
101 {
102   SILC_LOG_DEBUG(("test_st_finish"));
103
104   SILC_LOG_DEBUG(("Finish machine"));
105   return SILC_FSM_FINISH;
106 }
107
108 static void destructor(SilcFSM fsm, void *fsm_context,
109                        void *destructor_context)
110 {
111   SILC_LOG_DEBUG(("FSM destructor, stopping scheduler"));
112   silc_fsm_free(fsm);
113   silc_schedule_stop(schedule);
114 }
115
116 int main(int argc, char **argv)
117 {
118   SilcBool success = FALSE;
119   SilcFSM fsm;
120   Foo f;
121
122   if (argc > 1 && !strcmp(argv[1], "-d")) {
123     silc_log_debug(TRUE);
124     silc_log_debug_hexdump(TRUE);
125     silc_log_set_debug_string("*async*");
126   }
127
128   SILC_LOG_DEBUG(("Allocating scheduler"));
129   schedule = silc_schedule_init(0, NULL);
130
131   f = silc_calloc(1, sizeof(*f));
132   if (!f)
133     goto err;
134
135   SILC_LOG_DEBUG(("Allocating FSM context"));
136   fsm = silc_fsm_alloc(f, destructor, NULL, schedule);
137   if (!fsm)
138     goto err;
139   silc_fsm_start(fsm, test_st_start);
140   f->fsm = fsm;
141
142   SILC_LOG_DEBUG(("Running scheduler"));
143   silc_schedule(schedule);
144
145   if (!f->aborted)
146     goto err;
147
148   silc_schedule_uninit(schedule);
149   silc_free(f);
150
151   success = TRUE;
152
153  err:
154   SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
155   fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
156
157   return success;
158 }