Added SILC Thread Queue API
[silc.git] / lib / silcutil / tests / test_silcfdstream.c
1 /* SILC FD Stream tests */
2
3 #include "silc.h"
4
5 SilcBool success = FALSE;
6 SilcSchedule schedule;
7 SilcStream stream;
8 char buf1[10240];
9 int buf1_len = sizeof(buf1);
10
11 static void stream_notifier(SilcStream stream, SilcStreamStatus status,
12                             void *context)
13 {
14   SILC_LOG_DEBUG(("Notifier"));
15
16   /* XXX we probably never get here with this test program */
17
18   silc_fsm_continue(context);
19 }
20
21 static void stream_notifier2(SilcStream stream, SilcStreamStatus status,
22                              void *context)
23 {
24   SILC_LOG_DEBUG(("Notifier"));
25
26   /* XXX we probably never get here with this test program */
27
28   silc_fsm_continue(context);
29 }
30
31 SILC_FSM_STATE(st_end)
32 {
33   unlink("/tmp/test_silcfdstream");
34   unlink("/tmp/test_silcfdstream_copy");
35   return SILC_FSM_FINISH;
36 }
37
38 SILC_FSM_STATE(st_readwrite)
39 {
40   int ret, i, k, fd1, fd2;
41   char *cp;
42
43   SILC_LOG_DEBUG(("Opening two files, one for reading, one for writing"));
44
45   SILC_LOG_DEBUG(("Open file /tmp/test_silcfdstream for reading"));
46   fd1 = silc_file_open("/tmp/test_silcfdstream", O_RDONLY);
47   if (fd1 < 0) {
48     SILC_LOG_DEBUG(("Error opening file"));
49     goto err;
50   }
51
52   SILC_LOG_DEBUG(("Open file /tmp/test_silcfdstream_copy for writing"));
53   unlink("/tmp/test_silcfdstream_copy");
54   fd2 = silc_file_open("/tmp/test_silcfdstream_copy", O_CREAT | O_WRONLY);
55   if (fd2 < 0) {
56     SILC_LOG_DEBUG(("Error opening file"));
57     goto err;
58   }
59
60   SILC_LOG_DEBUG(("Creating FD stream (two fds)"));
61   stream = silc_fd_stream_create2(fd1, fd2, NULL);
62   if (!stream) {
63     SILC_LOG_DEBUG(("Error creating stream"));
64     goto err;
65   }
66
67   silc_stream_set_notifier(stream, schedule, stream_notifier2, fsm);
68
69   /* Stream between the fiels */
70   SILC_LOG_DEBUG(("Read/write 3 bytes at a time"));
71   memset(buf1, 0, sizeof(buf1));
72   while ((ret = silc_stream_read(stream, buf1, 3)) > 0) {
73     k = ret;
74     cp = buf1;
75     while (k > 0) {
76       i = silc_stream_write(stream, cp, k);
77
78       if (i == 0) {
79         SILC_LOG_DEBUG(("EOF"));
80         goto err;
81       }
82
83       if (i == -1) {
84         SILC_LOG_DEBUG(("Would block, write later"));
85         silc_fsm_next(fsm, st_end);
86         return SILC_FSM_WAIT;
87       }
88
89       if (i == -2) {
90         SILC_LOG_DEBUG(("Error: %s", strerror(silc_fd_stream_get_error(stream))));
91         goto err;
92       }
93
94       k -= i;
95       cp += i;
96     }
97   }
98
99   if (ret == -1) {
100     SILC_LOG_DEBUG(("Would block, read later"));
101     silc_fsm_next(fsm, st_end);
102     return SILC_FSM_WAIT;
103   }
104
105   if (ret == -2) {
106     SILC_LOG_DEBUG(("Error: %s", strerror(silc_fd_stream_get_error(stream))));
107     goto err;
108   }
109
110   if (ret == 0) {
111     SILC_LOG_DEBUG(("EOF, ok"));
112     success = TRUE;
113     SILC_LOG_DEBUG(("Closing stream"));
114     silc_stream_close(stream);
115     SILC_LOG_DEBUG(("Destroying stream"));
116     silc_stream_destroy(stream);
117   }
118
119   silc_fsm_next(fsm, st_end);
120   return SILC_FSM_CONTINUE;
121
122  err:
123   silc_fsm_next(fsm, st_end);
124   return SILC_FSM_CONTINUE;
125 }
126
127 SILC_FSM_STATE(st_write)
128 {
129   int ret, i, k;
130   char *cp;
131
132   /* Simple writing example */
133   SILC_LOG_DEBUG(("Open file /tmp/test_silcfdstream for writing"));
134   SILC_LOG_DEBUG(("Creating FD stream"));
135   unlink("/tmp/test_silcfdstream");
136   stream = silc_fd_stream_file("/tmp/test_silcfdstream", FALSE, TRUE, NULL);
137   if (!stream) {
138     SILC_LOG_DEBUG(("Error creating stream"));
139     goto err;
140   }
141
142   silc_stream_set_notifier(stream, schedule, stream_notifier, fsm);
143
144   memset(buf1, 0, sizeof(buf1));
145   for (i = 0; i < sizeof(buf1); i++)
146     buf1[i] = i;
147
148   SILC_LOG_DEBUG(("Writing data"));
149   k = buf1_len;
150   cp = buf1;
151   while (k > 0) {
152     ret = silc_stream_write(stream, cp, k);
153
154     if (ret == 0) {
155       SILC_LOG_DEBUG(("EOF"));
156       goto err;
157     }
158
159     if (ret == -1) {
160       SILC_LOG_DEBUG(("Would block, write later"));
161       silc_fsm_next(fsm, st_readwrite);
162       return SILC_FSM_WAIT;
163     }
164
165     if (ret == -2) {
166       SILC_LOG_DEBUG(("Error: %s", strerror(silc_fd_stream_get_error(stream))));
167       goto err;
168     }
169
170     k -= ret;
171     cp += ret;
172   }
173
174   SILC_LOG_DEBUG(("Closing stream"));
175   silc_stream_close(stream);
176
177   SILC_LOG_DEBUG(("Destroying stream"));
178   silc_stream_destroy(stream);
179
180   SILC_LOG_DEBUG(("Continue to next state"));
181   silc_fsm_next(fsm, st_readwrite);
182   return SILC_FSM_CONTINUE;
183
184  err:
185   silc_fsm_next(fsm, st_end);
186   return SILC_FSM_CONTINUE;
187 }
188
189 static void fsm_dest(SilcFSM fsm, void *fsm_context, void *context)
190 {
191   silc_fsm_free(fsm);
192   silc_schedule_stop(schedule);
193 }
194
195 int main(int argc, char **argv)
196 {
197   SilcFSM fsm;
198
199   if (argc > 1 && !strcmp(argv[1], "-d")) {
200     silc_log_debug(TRUE);
201     silc_log_debug_hexdump(TRUE);
202     silc_log_set_debug_string("*fdstream*,*errno*");
203   }
204
205   SILC_LOG_DEBUG(("Allocating scheduler"));
206   schedule = silc_schedule_init(0, NULL, NULL);
207   if (!schedule)
208     goto err;
209
210   SILC_LOG_DEBUG(("Allocating FSM"));
211   fsm = silc_fsm_alloc(NULL, fsm_dest, NULL, schedule);
212   if (!fsm)
213     goto err;
214
215   silc_fsm_start(fsm, st_write);
216
217   SILC_LOG_DEBUG(("Running scheduler"));
218   silc_schedule(schedule);
219
220   if (!success)
221     goto err;
222
223   silc_schedule_uninit(schedule);
224   success = TRUE;
225
226  err:
227   SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
228   fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
229
230   return success;
231 }