unit-test: Link 29 test programs into ovstest
[sliver-openvswitch.git] / tests / test-reconnect.c
1 /*
2  * Copyright (c) 2009, 2010, 2011, 2012, 2014 Nicira, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <config.h>
18
19 #include "reconnect.h"
20
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "command-line.h"
27 #include "compiler.h"
28 #include "svec.h"
29 #include "util.h"
30 #include "vlog.h"
31 #include "ovstest.h"
32
33 static struct reconnect *reconnect;
34 static int now;
35
36 static const struct command commands[];
37
38 static void diff_stats(const struct reconnect_stats *old,
39                        const struct reconnect_stats *new,
40                        int delta);
41
42 static void
43 test_reconnect_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
44 {
45     extern struct vlog_module VLM_reconnect;
46     struct reconnect_stats prev;
47     unsigned int old_max_tries;
48     int old_time;
49     char line[128];
50
51     vlog_set_levels(&VLM_reconnect, VLF_ANY_FACILITY, VLL_OFF);
52
53     now = 1000;
54     reconnect = reconnect_create(now);
55     reconnect_set_name(reconnect, "remote");
56     reconnect_get_stats(reconnect, now, &prev);
57     printf("### t=%d ###\n", now);
58     old_time = now;
59     old_max_tries = reconnect_get_max_tries(reconnect);
60     while (fgets(line, sizeof line, stdin)) {
61         struct reconnect_stats cur;
62         struct svec args;
63
64         fputs(line, stdout);
65         if (line[0] == '#') {
66             continue;
67         }
68
69         svec_init(&args);
70         svec_parse_words(&args, line);
71         svec_terminate(&args);
72         if (!svec_is_empty(&args)) {
73             run_command(args.n, args.names, commands);
74         }
75         svec_destroy(&args);
76
77         if (old_time != now) {
78             printf("\n### t=%d ###\n", now);
79         }
80
81         reconnect_get_stats(reconnect, now, &cur);
82         diff_stats(&prev, &cur, now - old_time);
83         prev = cur;
84         if (reconnect_get_max_tries(reconnect) != old_max_tries) {
85             old_max_tries = reconnect_get_max_tries(reconnect);
86             printf("  %u tries left\n", old_max_tries);
87         }
88
89         old_time = now;
90     }
91 }
92
93 static void
94 do_enable(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
95 {
96     reconnect_enable(reconnect, now);
97 }
98
99 static void
100 do_disable(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
101 {
102     reconnect_disable(reconnect, now);
103 }
104
105 static void
106 do_force_reconnect(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
107 {
108     reconnect_force_reconnect(reconnect, now);
109 }
110
111 static int
112 error_from_string(const char *s)
113 {
114     if (!s) {
115         return 0;
116     } else if (!strcmp(s, "ECONNREFUSED")) {
117         return ECONNREFUSED;
118     } else if (!strcmp(s, "EOF")) {
119         return EOF;
120     } else {
121         ovs_fatal(0, "unknown error '%s'", s);
122     }
123 }
124
125 static void
126 do_disconnected(int argc OVS_UNUSED, char *argv[])
127 {
128     reconnect_disconnected(reconnect, now, error_from_string(argv[1]));
129 }
130
131 static void
132 do_connecting(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
133 {
134     reconnect_connecting(reconnect, now);
135 }
136
137 static void
138 do_connect_failed(int argc OVS_UNUSED, char *argv[])
139 {
140     reconnect_connect_failed(reconnect, now, error_from_string(argv[1]));
141 }
142
143 static void
144 do_connected(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
145 {
146     reconnect_connected(reconnect, now);
147 }
148
149 static void
150 do_activity(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
151 {
152     reconnect_activity(reconnect, now);
153 }
154
155 static void
156 do_run(int argc, char *argv[])
157 {
158     enum reconnect_action action;
159
160     if (argc > 1) {
161         now += atoi(argv[1]);
162     }
163
164     action = reconnect_run(reconnect, now);
165     switch (action) {
166     default:
167         if (action != 0) {
168             OVS_NOT_REACHED();
169         }
170         break;
171
172     case RECONNECT_CONNECT:
173         printf("  should connect\n");
174         break;
175
176     case RECONNECT_DISCONNECT:
177         printf("  should disconnect\n");
178         break;
179
180     case RECONNECT_PROBE:
181         printf("  should send probe\n");
182         break;
183     }
184 }
185
186 static void
187 do_advance(int argc OVS_UNUSED, char *argv[])
188 {
189     now += atoi(argv[1]);
190 }
191
192 static void
193 do_timeout(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
194 {
195     int timeout = reconnect_timeout(reconnect, now);
196     if (timeout >= 0) {
197         printf("  advance %d ms\n", timeout);
198         now += timeout;
199     } else {
200         printf("  no timeout\n");
201     }
202 }
203
204 static void
205 do_set_max_tries(int argc OVS_UNUSED, char *argv[])
206 {
207     reconnect_set_max_tries(reconnect, atoi(argv[1]));
208 }
209
210 static void
211 diff_stats(const struct reconnect_stats *old,
212            const struct reconnect_stats *new,
213            int delta)
214 {
215     if (old->state != new->state
216         || old->state_elapsed != new->state_elapsed
217         || old->backoff != new->backoff) {
218         printf("  in %s for %u ms (%d ms backoff)\n",
219                new->state, new->state_elapsed, new->backoff);
220     }
221     if (old->creation_time != new->creation_time
222         || old->last_activity != new->last_activity
223         || old->last_connected != new->last_connected) {
224         printf("  created %lld, last activity %lld, last connected %lld\n",
225                new->creation_time, new->last_activity, new->last_connected);
226     }
227     if (old->n_successful_connections != new->n_successful_connections
228         || old->n_attempted_connections != new->n_attempted_connections
229         || old->seqno != new->seqno) {
230         printf("  %u successful connections out of %u attempts, seqno %u\n",
231                new->n_successful_connections, new->n_attempted_connections,
232                new->seqno);
233     }
234     if (old->is_connected != new->is_connected) {
235         printf("  %sconnected\n", new->is_connected ? "" : "dis");
236     }
237     if (old->last_connected != new->last_connected
238         || (old->msec_since_connect != new->msec_since_connect - delta
239             && !(old->msec_since_connect == UINT_MAX
240                  && new->msec_since_connect == UINT_MAX))
241         || (old->total_connected_duration != new->total_connected_duration - delta
242             && !(old->total_connected_duration == 0
243                  && new->total_connected_duration == 0))) {
244         printf("  last connected %u ms ago, connected %u ms total\n",
245                new->msec_since_connect, new->total_connected_duration);
246     }
247     if (old->last_disconnected != new->last_disconnected
248         || (old->msec_since_disconnect != new->msec_since_disconnect - delta
249             && !(old->msec_since_disconnect == UINT_MAX
250                  && new->msec_since_disconnect == UINT_MAX))) {
251         printf("  disconnected at %llu ms (%u ms ago)\n",
252                new->last_disconnected, new->msec_since_disconnect);
253     }
254 }
255
256 static void
257 do_set_passive(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
258 {
259     reconnect_set_passive(reconnect, true, now);
260 }
261
262 static void
263 do_listening(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
264 {
265     reconnect_listening(reconnect, now);
266 }
267
268 static void
269 do_listen_error(int argc OVS_UNUSED, char *argv[])
270 {
271     reconnect_listen_error(reconnect, now, atoi(argv[1]));
272 }
273
274 static const struct command commands[] = {
275     { "enable", 0, 0, do_enable },
276     { "disable", 0, 0, do_disable },
277     { "force-reconnect", 0, 0, do_force_reconnect },
278     { "disconnected", 0, 1, do_disconnected },
279     { "connecting", 0, 0, do_connecting },
280     { "connect-failed", 0, 1, do_connect_failed },
281     { "connected", 0, 0, do_connected },
282     { "activity", 0, 0, do_activity },
283     { "run", 0, 1, do_run },
284     { "advance", 1, 1, do_advance },
285     { "timeout", 0, 0, do_timeout },
286     { "set-max-tries", 1, 1, do_set_max_tries },
287     { "passive", 0, 0, do_set_passive },
288     { "listening", 0, 0, do_listening },
289     { "listen-error", 1, 1, do_listen_error },
290     { NULL, 0, 0, NULL },
291 };
292
293 OVSTEST_REGISTER("test-reconnect", test_reconnect_main);