api: Cleanup APIs interface.api
[vpp.git] / test / ext / vapi_c_test.c
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2017 Cisco and/or its affiliates.
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
18 #include <stdio.h>
19 #include <endian.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <assert.h>
23 #include <setjmp.h>
24 #include <check.h>
25 #include <vppinfra/string.h>
26 #include <vapi/vapi.h>
27 #include <vapi/vpe.api.vapi.h>
28 #include <vapi/interface.api.vapi.h>
29 #include <vapi/l2.api.vapi.h>
30 #include <fake.api.vapi.h>
31
32 DEFINE_VAPI_MSG_IDS_VPE_API_JSON;
33 DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON;
34 DEFINE_VAPI_MSG_IDS_L2_API_JSON;
35 DEFINE_VAPI_MSG_IDS_FAKE_API_JSON;
36
37 static char *app_name = NULL;
38 static char *api_prefix = NULL;
39 static const int max_outstanding_requests = 64;
40 static const int response_queue_size = 32;
41
42 /* centos has ancient check so we hack our way around here
43  * to make it work somehow */
44 #ifndef ck_assert_ptr_eq
45 #define ck_assert_ptr_eq(X,Y) ck_assert_int_eq((long)X, (long)Y)
46 #endif
47
48 #ifndef ck_assert_ptr_ne
49 #define ck_assert_ptr_ne(X,Y) ck_assert_int_ne((long)X, (long)Y)
50 #endif
51
52 START_TEST (test_invalid_values)
53 {
54   vapi_ctx_t ctx;
55   vapi_error_e rv = vapi_ctx_alloc (&ctx);
56   ck_assert_int_eq (VAPI_OK, rv);
57   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
58   ck_assert_ptr_eq (NULL, sv);
59   rv = vapi_send (ctx, sv);
60   ck_assert_int_eq (VAPI_EINVAL, rv);
61   rv = vapi_connect (ctx, app_name, api_prefix, max_outstanding_requests,
62                      response_queue_size, VAPI_MODE_BLOCKING, true);
63   ck_assert_int_eq (VAPI_OK, rv);
64   rv = vapi_send (ctx, NULL);
65   ck_assert_int_eq (VAPI_EINVAL, rv);
66   rv = vapi_send (NULL, NULL);
67   ck_assert_int_eq (VAPI_EINVAL, rv);
68   rv = vapi_recv (NULL, NULL, NULL, 0, 0);
69   ck_assert_int_eq (VAPI_EINVAL, rv);
70   rv = vapi_recv (ctx, NULL, NULL, 0, 0);
71   ck_assert_int_eq (VAPI_EINVAL, rv);
72   vapi_msg_show_version_reply *reply;
73   rv = vapi_recv (ctx, (void **) &reply, NULL, 0, 0);
74   ck_assert_int_eq (VAPI_EINVAL, rv);
75   rv = vapi_disconnect (ctx);
76   ck_assert_int_eq (VAPI_OK, rv);
77   vapi_ctx_free (ctx);
78 }
79
80 END_TEST;
81
82 START_TEST (test_hton_1)
83 {
84   const u16 _vl_msg_id = 1;
85   vapi_type_msg_header1_t h;
86   h._vl_msg_id = _vl_msg_id;
87   vapi_type_msg_header1_t_hton (&h);
88   ck_assert_int_eq (be16toh (h._vl_msg_id), _vl_msg_id);
89 }
90
91 END_TEST;
92
93 START_TEST (test_hton_2)
94 {
95   const u16 _vl_msg_id = 1;
96   const u32 client_index = 3;
97   vapi_type_msg_header2_t h;
98   h._vl_msg_id = _vl_msg_id;
99   h.client_index = client_index;
100   vapi_type_msg_header2_t_hton (&h);
101   ck_assert_int_eq (be16toh (h._vl_msg_id), _vl_msg_id);
102   ck_assert_int_eq (h.client_index, client_index);
103 }
104
105 END_TEST;
106
107 #define verify_hton_swap(expr, value)           \
108   if (4 == sizeof (expr))                       \
109     {                                           \
110       ck_assert_int_eq (expr, htobe32 (value)); \
111     }                                           \
112   else if (2 == sizeof (expr))                  \
113     {                                           \
114       ck_assert_int_eq (expr, htobe16 (value)); \
115     }                                           \
116   else                                          \
117     {                                           \
118       ck_assert_int_eq (expr, value);           \
119     }
120
121 START_TEST (test_hton_4)
122 {
123   const int vla_count = 3;
124   char x[sizeof (vapi_msg_bridge_domain_details) +
125          vla_count * sizeof (vapi_type_bridge_domain_sw_if)];
126   vapi_msg_bridge_domain_details *d = (void *) x;
127   int cnt = 1;
128   d->header._vl_msg_id = cnt++;
129   d->header.context = cnt++;
130   d->payload.bd_id = cnt++;
131   d->payload.flood = cnt++;
132   d->payload.uu_flood = cnt++;
133   d->payload.forward = cnt++;
134   d->payload.learn = cnt++;
135   d->payload.arp_term = cnt++;
136   d->payload.mac_age = cnt++;
137   d->payload.bvi_sw_if_index = cnt++;
138   d->payload.n_sw_ifs = vla_count;
139   int i;
140   for (i = 0; i < vla_count; ++i)
141     {
142       vapi_type_bridge_domain_sw_if *det = &d->payload.sw_if_details[i];
143       det->context = cnt++;
144       det->sw_if_index = cnt++;
145       det->shg = cnt++;
146     }
147   ck_assert_int_eq (sizeof (x), vapi_calc_bridge_domain_details_msg_size (d));
148   vapi_msg_bridge_domain_details_hton (d);
149   int tmp = 1;
150   verify_hton_swap (d->header._vl_msg_id, tmp);
151   ++tmp;
152   ck_assert_int_eq (d->header.context, tmp);
153   ++tmp;
154   verify_hton_swap (d->payload.bd_id, tmp);
155   ++tmp;
156   verify_hton_swap (d->payload.flood, tmp);
157   ++tmp;
158   verify_hton_swap (d->payload.uu_flood, tmp);
159   ++tmp;
160   verify_hton_swap (d->payload.forward, tmp);
161   ++tmp;
162   verify_hton_swap (d->payload.learn, tmp);
163   ++tmp;
164   verify_hton_swap (d->payload.arp_term, tmp);
165   ++tmp;
166   verify_hton_swap (d->payload.mac_age, tmp);
167   ++tmp;
168   verify_hton_swap (d->payload.bvi_sw_if_index, tmp);
169   ++tmp;
170   ck_assert_int_eq (d->payload.n_sw_ifs, htobe32 (vla_count));
171   for (i = 0; i < vla_count; ++i)
172     {
173       vapi_type_bridge_domain_sw_if *det = &d->payload.sw_if_details[i];
174       verify_hton_swap (det->context, tmp);
175       ++tmp;
176       verify_hton_swap (det->sw_if_index, tmp);
177       ++tmp;
178       verify_hton_swap (det->shg, tmp);
179       ++tmp;
180     }
181   vapi_msg_bridge_domain_details_ntoh (d);
182   tmp = 1;
183   ck_assert_int_eq (d->header._vl_msg_id, tmp);
184   ++tmp;
185   ck_assert_int_eq (d->header.context, tmp);
186   ++tmp;
187   ck_assert_int_eq (d->payload.bd_id, tmp);
188   ++tmp;
189   ck_assert_int_eq (d->payload.flood, tmp);
190   ++tmp;
191   ck_assert_int_eq (d->payload.uu_flood, tmp);
192   ++tmp;
193   ck_assert_int_eq (d->payload.forward, tmp);
194   ++tmp;
195   ck_assert_int_eq (d->payload.learn, tmp);
196   ++tmp;
197   ck_assert_int_eq (d->payload.arp_term, tmp);
198   ++tmp;
199   ck_assert_int_eq (d->payload.mac_age, tmp);
200   ++tmp;
201   ck_assert_int_eq (d->payload.bvi_sw_if_index, tmp);
202   ++tmp;
203   ck_assert_int_eq (d->payload.n_sw_ifs, vla_count);
204   for (i = 0; i < vla_count; ++i)
205     {
206       vapi_type_bridge_domain_sw_if *det = &d->payload.sw_if_details[i];
207       ck_assert_int_eq (det->context, tmp);
208       ++tmp;
209       ck_assert_int_eq (det->sw_if_index, tmp);
210       ++tmp;
211       ck_assert_int_eq (det->shg, tmp);
212       ++tmp;
213     }
214   ck_assert_int_eq (sizeof (x), vapi_calc_bridge_domain_details_msg_size (d));
215 }
216
217 END_TEST;
218
219 START_TEST (test_ntoh_1)
220 {
221   const u16 _vl_msg_id = 1;
222   vapi_type_msg_header1_t h;
223   h._vl_msg_id = _vl_msg_id;
224   vapi_type_msg_header1_t_ntoh (&h);
225   ck_assert_int_eq (htobe16 (h._vl_msg_id), _vl_msg_id);
226 }
227
228 END_TEST;
229
230 START_TEST (test_ntoh_2)
231 {
232   const u16 _vl_msg_id = 1;
233   const u32 client_index = 3;
234   vapi_type_msg_header2_t h;
235   h._vl_msg_id = _vl_msg_id;
236   h.client_index = client_index;
237   vapi_type_msg_header2_t_ntoh (&h);
238   ck_assert_int_eq (htobe16 (h._vl_msg_id), _vl_msg_id);
239   ck_assert_int_eq (h.client_index, client_index);
240 }
241
242 END_TEST;
243
244 #define verify_ntoh_swap(expr, value)           \
245   if (4 == sizeof (expr))                       \
246     {                                           \
247       ck_assert_int_eq (expr, be32toh (value)); \
248     }                                           \
249   else if (2 == sizeof (expr))                  \
250     {                                           \
251       ck_assert_int_eq (expr, be16toh (value)); \
252     }                                           \
253   else                                          \
254     {                                           \
255       ck_assert_int_eq (expr, value);           \
256     }
257
258 START_TEST (test_ntoh_4)
259 {
260   const int vla_count = 3;
261   char x[sizeof (vapi_msg_bridge_domain_details) +
262          vla_count * sizeof (vapi_type_bridge_domain_sw_if)];
263   vapi_msg_bridge_domain_details *d = (void *) x;
264   int cnt = 1;
265   d->header._vl_msg_id = cnt++;
266   d->header.context = cnt++;
267   d->payload.bd_id = cnt++;
268   d->payload.flood = cnt++;
269   d->payload.uu_flood = cnt++;
270   d->payload.forward = cnt++;
271   d->payload.learn = cnt++;
272   d->payload.arp_term = cnt++;
273   d->payload.mac_age = cnt++;
274   d->payload.bvi_sw_if_index = cnt++;
275   d->payload.n_sw_ifs = htobe32 (vla_count);
276   int i;
277   for (i = 0; i < vla_count; ++i)
278     {
279       vapi_type_bridge_domain_sw_if *det = &d->payload.sw_if_details[i];
280       det->context = cnt++;
281       det->sw_if_index = cnt++;
282       det->shg = cnt++;
283     }
284   vapi_msg_bridge_domain_details_ntoh (d);
285   ck_assert_int_eq (sizeof (x), vapi_calc_bridge_domain_details_msg_size (d));
286   int tmp = 1;
287   verify_ntoh_swap (d->header._vl_msg_id, tmp);
288   ++tmp;
289   ck_assert_int_eq (d->header.context, tmp);
290   ++tmp;
291   verify_ntoh_swap (d->payload.bd_id, tmp);
292   ++tmp;
293   verify_ntoh_swap (d->payload.flood, tmp);
294   ++tmp;
295   verify_ntoh_swap (d->payload.uu_flood, tmp);
296   ++tmp;
297   verify_ntoh_swap (d->payload.forward, tmp);
298   ++tmp;
299   verify_ntoh_swap (d->payload.learn, tmp);
300   ++tmp;
301   verify_ntoh_swap (d->payload.arp_term, tmp);
302   ++tmp;
303   verify_ntoh_swap (d->payload.mac_age, tmp);
304   ++tmp;
305   verify_ntoh_swap (d->payload.bvi_sw_if_index, tmp);
306   ++tmp;
307   ck_assert_int_eq (d->payload.n_sw_ifs, vla_count);
308   for (i = 0; i < vla_count; ++i)
309     {
310       vapi_type_bridge_domain_sw_if *det = &d->payload.sw_if_details[i];
311       verify_ntoh_swap (det->context, tmp);
312       ++tmp;
313       verify_ntoh_swap (det->sw_if_index, tmp);
314       ++tmp;
315       verify_ntoh_swap (det->shg, tmp);
316       ++tmp;
317     }
318   vapi_msg_bridge_domain_details_hton (d);
319   tmp = 1;
320   ck_assert_int_eq (d->header._vl_msg_id, tmp);
321   ++tmp;
322   ck_assert_int_eq (d->header.context, tmp);
323   ++tmp;
324   ck_assert_int_eq (d->payload.bd_id, tmp);
325   ++tmp;
326   ck_assert_int_eq (d->payload.flood, tmp);
327   ++tmp;
328   ck_assert_int_eq (d->payload.uu_flood, tmp);
329   ++tmp;
330   ck_assert_int_eq (d->payload.forward, tmp);
331   ++tmp;
332   ck_assert_int_eq (d->payload.learn, tmp);
333   ++tmp;
334   ck_assert_int_eq (d->payload.arp_term, tmp);
335   ++tmp;
336   ck_assert_int_eq (d->payload.mac_age, tmp);
337   ++tmp;
338   ck_assert_int_eq (d->payload.bvi_sw_if_index, tmp);
339   ++tmp;
340   ck_assert_int_eq (d->payload.n_sw_ifs, htobe32 (vla_count));
341   for (i = 0; i < vla_count; ++i)
342     {
343       vapi_type_bridge_domain_sw_if *det = &d->payload.sw_if_details[i];
344       ck_assert_int_eq (det->context, tmp);
345       ++tmp;
346       ck_assert_int_eq (det->sw_if_index, tmp);
347       ++tmp;
348       ck_assert_int_eq (det->shg, tmp);
349       ++tmp;
350     }
351 }
352
353 END_TEST;
354
355 vapi_error_e
356 show_version_cb (vapi_ctx_t ctx, void *caller_ctx,
357                  vapi_error_e rv, bool is_last,
358                  vapi_payload_show_version_reply * p)
359 {
360   ck_assert_int_eq (VAPI_OK, rv);
361   ck_assert_int_eq (true, is_last);
362   ck_assert_str_eq ("vpe", (char *) vl_api_from_api_string (&p->program));
363   printf
364     ("show_version_reply: program: `%s', version: `%s', build directory: "
365      "`%s', build date: `%s'\n",
366      vl_api_from_api_string (&p->program),
367      vl_api_from_api_string (&p->version),
368      vl_api_from_api_string (&p->build_directory),
369      vl_api_from_api_string (&p->build_date));
370   ++*(int *) caller_ctx;
371   return VAPI_OK;
372 }
373
374 typedef struct
375 {
376   int called;
377   int expected_retval;
378   u32 *sw_if_index_storage;
379 } test_create_loopback_ctx_t;
380
381 vapi_error_e
382 loopback_create_cb (vapi_ctx_t ctx, void *caller_ctx,
383                     vapi_error_e rv, bool is_last,
384                     vapi_payload_create_loopback_reply * p)
385 {
386   test_create_loopback_ctx_t *clc = caller_ctx;
387   ck_assert_int_eq (clc->expected_retval, p->retval);
388   *clc->sw_if_index_storage = p->sw_if_index;
389   ++clc->called;
390   return VAPI_OK;
391 }
392
393 typedef struct
394 {
395   int called;
396   int expected_retval;
397   u32 *sw_if_index_storage;
398 } test_delete_loopback_ctx_t;
399
400 vapi_error_e
401 loopback_delete_cb (vapi_ctx_t ctx, void *caller_ctx,
402                     vapi_error_e rv, bool is_last,
403                     vapi_payload_delete_loopback_reply * p)
404 {
405   test_delete_loopback_ctx_t *dlc = caller_ctx;
406   ck_assert_int_eq (dlc->expected_retval, p->retval);
407   ++dlc->called;
408   return VAPI_OK;
409 }
410
411 START_TEST (test_connect)
412 {
413   vapi_ctx_t ctx;
414   vapi_error_e rv = vapi_ctx_alloc (&ctx);
415   ck_assert_int_eq (VAPI_OK, rv);
416   rv = vapi_connect (ctx, app_name, api_prefix, max_outstanding_requests,
417                      response_queue_size, VAPI_MODE_BLOCKING, true);
418   ck_assert_int_eq (VAPI_OK, rv);
419   rv = vapi_disconnect (ctx);
420   ck_assert_int_eq (VAPI_OK, rv);
421   vapi_ctx_free (ctx);
422 }
423
424 END_TEST;
425
426 vapi_ctx_t ctx;
427
428 void
429 setup_blocking (void)
430 {
431   vapi_error_e rv = vapi_ctx_alloc (&ctx);
432   ck_assert_int_eq (VAPI_OK, rv);
433   rv = vapi_connect (ctx, app_name, api_prefix, max_outstanding_requests,
434                      response_queue_size, VAPI_MODE_BLOCKING, true);
435   ck_assert_int_eq (VAPI_OK, rv);
436 }
437
438 void
439 setup_nonblocking (void)
440 {
441   vapi_error_e rv = vapi_ctx_alloc (&ctx);
442   ck_assert_int_eq (VAPI_OK, rv);
443   rv = vapi_connect (ctx, app_name, api_prefix, max_outstanding_requests,
444                      response_queue_size, VAPI_MODE_NONBLOCKING, true);
445   ck_assert_int_eq (VAPI_OK, rv);
446 }
447
448 void
449 teardown (void)
450 {
451   vapi_disconnect (ctx);
452   vapi_ctx_free (ctx);
453 }
454
455 START_TEST (test_show_version_1)
456 {
457   printf ("--- Basic show version message - reply test ---\n");
458   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
459   ck_assert_ptr_ne (NULL, sv);
460   vapi_msg_show_version_hton (sv);
461   vapi_error_e rv = vapi_send (ctx, sv);
462   ck_assert_int_eq (VAPI_OK, rv);
463   vapi_msg_show_version_reply *resp;
464   size_t size;
465   rv = vapi_recv (ctx, (void *) &resp, &size, 0, 0);
466   ck_assert_int_eq (VAPI_OK, rv);
467   int dummy;
468   show_version_cb (NULL, &dummy, VAPI_OK, true, &resp->payload);
469   vapi_msg_free (ctx, resp);
470 }
471
472 END_TEST;
473
474 START_TEST (test_show_version_2)
475 {
476   int called = 0;
477   printf ("--- Show version via blocking callback API ---\n");
478   const int attempts = response_queue_size * 4;
479   int i = 0;
480   for (i = 0; i < attempts; ++i)
481     {
482       vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
483       ck_assert_ptr_ne (NULL, sv);
484       vapi_error_e rv = vapi_show_version (ctx, sv, show_version_cb, &called);
485       ck_assert_int_eq (VAPI_OK, rv);
486     }
487   ck_assert_int_eq (attempts, called);
488 }
489
490 END_TEST;
491
492 typedef struct
493 {
494   bool last_called;
495   size_t num_ifs;
496   u32 *sw_if_indexes;
497   bool *seen;
498   int called;
499 } sw_interface_dump_ctx;
500
501 vapi_error_e
502 sw_interface_dump_cb (struct vapi_ctx_s *ctx, void *callback_ctx,
503                       vapi_error_e rv, bool is_last,
504                       vapi_payload_sw_interface_details * reply)
505 {
506   sw_interface_dump_ctx *dctx = callback_ctx;
507   ck_assert_int_eq (false, dctx->last_called);
508   if (is_last)
509     {
510       ck_assert (NULL == reply);
511       dctx->last_called = true;
512     }
513   else
514     {
515       ck_assert (NULL != reply);
516       printf ("Interface dump entry: [%u]: %s\n", reply->sw_if_index,
517               reply->interface_name.buf);
518       size_t i = 0;
519       for (i = 0; i < dctx->num_ifs; ++i)
520         {
521           if (dctx->sw_if_indexes[i] == reply->sw_if_index)
522             {
523               ck_assert_int_eq (false, dctx->seen[i]);
524               dctx->seen[i] = true;
525             }
526         }
527     }
528   ++dctx->called;
529   return VAPI_OK;
530 }
531
532 START_TEST (test_loopbacks_1)
533 {
534   printf ("--- Create/delete loopbacks using blocking API ---\n");
535   const size_t num_ifs = 5;
536   u8 mac_addresses[num_ifs][6];
537   clib_memset (&mac_addresses, 0, sizeof (mac_addresses));
538   u32 sw_if_indexes[num_ifs];
539   clib_memset (&sw_if_indexes, 0xff, sizeof (sw_if_indexes));
540   test_create_loopback_ctx_t clcs[num_ifs];
541   clib_memset (&clcs, 0, sizeof (clcs));
542   test_delete_loopback_ctx_t dlcs[num_ifs];
543   clib_memset (&dlcs, 0, sizeof (dlcs));
544   int i;
545   for (i = 0; i < num_ifs; ++i)
546     {
547       memcpy (&mac_addresses[i], "\1\2\3\4\5\6", 6);
548       mac_addresses[i][5] = i;
549       clcs[i].sw_if_index_storage = &sw_if_indexes[i];
550     }
551   for (i = 0; i < num_ifs; ++i)
552     {
553       vapi_msg_create_loopback *cl = vapi_alloc_create_loopback (ctx);
554       memcpy (cl->payload.mac_address, mac_addresses[i],
555               sizeof (cl->payload.mac_address));
556       vapi_error_e rv =
557         vapi_create_loopback (ctx, cl, loopback_create_cb, &clcs[i]);
558       ck_assert_int_eq (VAPI_OK, rv);
559     }
560   for (i = 0; i < num_ifs; ++i)
561     {
562       ck_assert_int_eq (1, clcs[i].called);
563       printf ("Created loopback with MAC %02x:%02x:%02x:%02x:%02x:%02x --> "
564               "sw_if_index %u\n",
565               mac_addresses[i][0], mac_addresses[i][1], mac_addresses[i][2],
566               mac_addresses[i][3], mac_addresses[i][4], mac_addresses[i][5],
567               sw_if_indexes[i]);
568     }
569   bool seen[num_ifs];
570   sw_interface_dump_ctx dctx = { false, num_ifs, sw_if_indexes, seen, 0 };
571   vapi_msg_sw_interface_dump *dump;
572   vapi_error_e rv;
573   const int attempts = response_queue_size * 4;
574   for (i = 0; i < attempts; ++i)
575     {
576       dctx.last_called = false;
577       clib_memset (&seen, 0, sizeof (seen));
578       dump = vapi_alloc_sw_interface_dump (ctx);
579       dump->payload.name_filter_valid = 0;
580       clib_memset (dump->payload.name_filter.buf, 0,
581                    dump->payload.name_filter.length);
582       while (VAPI_EAGAIN ==
583              (rv =
584               vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb,
585                                       &dctx)))
586         ;
587       ck_assert_int_eq (true, dctx.last_called);
588       int j = 0;
589       for (j = 0; j < num_ifs; ++j)
590         {
591           ck_assert_int_eq (true, seen[j]);
592         }
593     }
594   clib_memset (&seen, 0, sizeof (seen));
595   for (i = 0; i < num_ifs; ++i)
596     {
597       vapi_msg_delete_loopback *dl = vapi_alloc_delete_loopback (ctx);
598       dl->payload.sw_if_index = sw_if_indexes[i];
599       vapi_error_e rv =
600         vapi_delete_loopback (ctx, dl, loopback_delete_cb, &dlcs[i]);
601       ck_assert_int_eq (VAPI_OK, rv);
602     }
603   for (i = 0; i < num_ifs; ++i)
604     {
605       ck_assert_int_eq (1, dlcs[i].called);
606       printf ("Deleted loopback with sw_if_index %u\n", sw_if_indexes[i]);
607     }
608   dctx.last_called = false;
609   clib_memset (&seen, 0, sizeof (seen));
610   dump = vapi_alloc_sw_interface_dump (ctx);
611   dump->payload.name_filter_valid = 0;
612   clib_memset (dump->payload.name_filter.buf, 0,
613                dump->payload.name_filter.length);
614   while (VAPI_EAGAIN ==
615          (rv =
616           vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb, &dctx)))
617     ;
618   ck_assert_int_eq (true, dctx.last_called);
619   for (i = 0; i < num_ifs; ++i)
620     {
621       ck_assert_int_eq (false, seen[i]);
622     }
623 }
624
625 END_TEST;
626
627 START_TEST (test_show_version_3)
628 {
629   printf ("--- Show version via async callback ---\n");
630   int called = 0;
631   vapi_error_e rv;
632   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
633   ck_assert_ptr_ne (NULL, sv);
634   while (VAPI_EAGAIN ==
635          (rv = vapi_show_version (ctx, sv, show_version_cb, &called)))
636     ;
637   ck_assert_int_eq (VAPI_OK, rv);
638   ck_assert_int_eq (0, called);
639   rv = vapi_dispatch (ctx);
640   ck_assert_int_eq (VAPI_OK, rv);
641   ck_assert_int_eq (1, called);
642   called = 0;
643   rv = vapi_dispatch (ctx);
644   ck_assert_int_eq (VAPI_OK, rv);
645   ck_assert_int_eq (0, called);
646 }
647
648 END_TEST;
649
650 START_TEST (test_show_version_4)
651 {
652   printf ("--- Show version via async callback - multiple messages ---\n");
653   vapi_error_e rv;
654   const size_t num_req = 5;
655   int contexts[num_req];
656   clib_memset (contexts, 0, sizeof (contexts));
657   int i;
658   for (i = 0; i < num_req; ++i)
659     {
660       vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
661       ck_assert_ptr_ne (NULL, sv);
662       while (VAPI_EAGAIN ==
663              (rv =
664               vapi_show_version (ctx, sv, show_version_cb, &contexts[i])))
665         ;
666       ck_assert_int_eq (VAPI_OK, rv);
667       int j;
668       for (j = 0; j < num_req; ++j)
669         {
670           ck_assert_int_eq (0, contexts[j]);
671         }
672     }
673   rv = vapi_dispatch (ctx);
674   ck_assert_int_eq (VAPI_OK, rv);
675   for (i = 0; i < num_req; ++i)
676     {
677       ck_assert_int_eq (1, contexts[i]);
678     }
679   clib_memset (contexts, 0, sizeof (contexts));
680   rv = vapi_dispatch (ctx);
681   ck_assert_int_eq (VAPI_OK, rv);
682   for (i = 0; i < num_req; ++i)
683     {
684       ck_assert_int_eq (0, contexts[i]);
685     }
686 }
687
688 END_TEST;
689
690 START_TEST (test_loopbacks_2)
691 {
692   printf ("--- Create/delete loopbacks using non-blocking API ---\n");
693   vapi_error_e rv;
694   const size_t num_ifs = 5;
695   u8 mac_addresses[num_ifs][6];
696   clib_memset (&mac_addresses, 0, sizeof (mac_addresses));
697   u32 sw_if_indexes[num_ifs];
698   clib_memset (&sw_if_indexes, 0xff, sizeof (sw_if_indexes));
699   test_create_loopback_ctx_t clcs[num_ifs];
700   clib_memset (&clcs, 0, sizeof (clcs));
701   test_delete_loopback_ctx_t dlcs[num_ifs];
702   clib_memset (&dlcs, 0, sizeof (dlcs));
703   int i;
704   for (i = 0; i < num_ifs; ++i)
705     {
706       memcpy (&mac_addresses[i], "\1\2\3\4\5\6", 6);
707       mac_addresses[i][5] = i;
708       clcs[i].sw_if_index_storage = &sw_if_indexes[i];
709     }
710   for (i = 0; i < num_ifs; ++i)
711     {
712       vapi_msg_create_loopback *cl = vapi_alloc_create_loopback (ctx);
713       memcpy (cl->payload.mac_address, mac_addresses[i],
714               sizeof (cl->payload.mac_address));
715       while (VAPI_EAGAIN ==
716              (rv =
717               vapi_create_loopback (ctx, cl, loopback_create_cb, &clcs[i])))
718         ;
719       ck_assert_int_eq (VAPI_OK, rv);
720     }
721   rv = vapi_dispatch (ctx);
722   ck_assert_int_eq (VAPI_OK, rv);
723   for (i = 0; i < num_ifs; ++i)
724     {
725       ck_assert_int_eq (1, clcs[i].called);
726       printf ("Loopback with MAC %02x:%02x:%02x:%02x:%02x:%02x --> "
727               "sw_if_index %u\n",
728               mac_addresses[i][0], mac_addresses[i][1], mac_addresses[i][2],
729               mac_addresses[i][3], mac_addresses[i][4], mac_addresses[i][5],
730               sw_if_indexes[i]);
731     }
732   bool seen[num_ifs];
733   clib_memset (&seen, 0, sizeof (seen));
734   sw_interface_dump_ctx dctx = { false, num_ifs, sw_if_indexes, seen, 0 };
735   vapi_msg_sw_interface_dump *dump = vapi_alloc_sw_interface_dump (ctx);
736   dump->payload.name_filter_valid = 0;
737   clib_memset (dump->payload.name_filter.buf, 0,
738                dump->payload.name_filter.length);
739   while (VAPI_EAGAIN ==
740          (rv =
741           vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb, &dctx)))
742     ;
743   for (i = 0; i < num_ifs; ++i)
744     {
745       ck_assert_int_eq (false, seen[i]);
746     }
747   clib_memset (&seen, 0, sizeof (seen));
748   ck_assert_int_eq (false, dctx.last_called);
749   rv = vapi_dispatch (ctx);
750   ck_assert_int_eq (VAPI_OK, rv);
751   for (i = 0; i < num_ifs; ++i)
752     {
753       ck_assert_int_eq (true, seen[i]);
754     }
755   clib_memset (&seen, 0, sizeof (seen));
756   ck_assert_int_eq (true, dctx.last_called);
757   for (i = 0; i < num_ifs; ++i)
758     {
759       vapi_msg_delete_loopback *dl = vapi_alloc_delete_loopback (ctx);
760       dl->payload.sw_if_index = sw_if_indexes[i];
761       while (VAPI_EAGAIN ==
762              (rv =
763               vapi_delete_loopback (ctx, dl, loopback_delete_cb, &dlcs[i])))
764         ;
765       ck_assert_int_eq (VAPI_OK, rv);
766     }
767   rv = vapi_dispatch (ctx);
768   ck_assert_int_eq (VAPI_OK, rv);
769   for (i = 0; i < num_ifs; ++i)
770     {
771       ck_assert_int_eq (1, dlcs[i].called);
772       printf ("Deleted loopback with sw_if_index %u\n", sw_if_indexes[i]);
773     }
774   clib_memset (&seen, 0, sizeof (seen));
775   dctx.last_called = false;
776   dump = vapi_alloc_sw_interface_dump (ctx);
777   dump->payload.name_filter_valid = 0;
778   clib_memset (dump->payload.name_filter.buf, 0,
779                dump->payload.name_filter.length);
780   while (VAPI_EAGAIN ==
781          (rv =
782           vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb, &dctx)))
783     ;
784   rv = vapi_dispatch (ctx);
785   ck_assert_int_eq (VAPI_OK, rv);
786   for (i = 0; i < num_ifs; ++i)
787     {
788       ck_assert_int_eq (false, seen[i]);
789     }
790   clib_memset (&seen, 0, sizeof (seen));
791   ck_assert_int_eq (true, dctx.last_called);
792 }
793
794 END_TEST;
795
796 vapi_error_e
797 generic_cb (vapi_ctx_t ctx, void *callback_ctx, vapi_msg_id_t id, void *msg)
798 {
799   int *called = callback_ctx;
800   ck_assert_int_eq (0, *called);
801   ++*called;
802   ck_assert_int_eq (id, vapi_msg_id_show_version_reply);
803   ck_assert_ptr_ne (NULL, msg);
804   vapi_msg_show_version_reply *reply = msg;
805   ck_assert_str_eq ("vpe",
806                     (char *) vl_api_from_api_string (&reply->
807                                                      payload.program));
808   return VAPI_OK;
809 }
810
811 START_TEST (test_show_version_5)
812 {
813   printf ("--- Receive show version using generic callback - nonblocking "
814           "API ---\n");
815   vapi_error_e rv;
816   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
817   ck_assert_ptr_ne (NULL, sv);
818   vapi_msg_show_version_hton (sv);
819   while (VAPI_EAGAIN == (rv = vapi_send (ctx, sv)))
820     ;
821   ck_assert_int_eq (VAPI_OK, rv);
822   int called = 0;
823   vapi_set_generic_event_cb (ctx, generic_cb, &called);
824   ck_assert_int_eq (VAPI_OK, rv);
825   rv = vapi_dispatch_one (ctx);
826   ck_assert_int_eq (VAPI_OK, rv);
827   ck_assert_int_eq (1, called);
828   sv = vapi_alloc_show_version (ctx);
829   ck_assert_ptr_ne (NULL, sv);
830   vapi_msg_show_version_hton (sv);
831   while (VAPI_EAGAIN == (rv = vapi_send (ctx, sv)))
832     ;
833   ck_assert_int_eq (VAPI_OK, rv);
834   vapi_clear_generic_event_cb (ctx);
835   rv = vapi_dispatch_one (ctx);
836   ck_assert_int_eq (VAPI_OK, rv);
837   ck_assert_int_eq (1, called); /* needs to remain unchanged */
838 }
839
840 END_TEST;
841
842 vapi_error_e
843 show_version_no_cb (vapi_ctx_t ctx, void *caller_ctx,
844                     vapi_error_e rv, bool is_last,
845                     vapi_payload_show_version_reply * p)
846 {
847   ck_assert_int_eq (VAPI_ENORESP, rv);
848   ck_assert_int_eq (true, is_last);
849   ck_assert_ptr_eq (NULL, p);
850   ++*(int *) caller_ctx;
851   return VAPI_OK;
852 }
853
854 START_TEST (test_no_response_1)
855 {
856   printf ("--- Simulate no response to regular message ---\n");
857   vapi_error_e rv;
858   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
859   ck_assert_ptr_ne (NULL, sv);
860   sv->header._vl_msg_id = ~0;   /* malformed ID causes vpp to drop the msg */
861   int called = 0;
862   while (VAPI_EAGAIN ==
863          (rv = vapi_show_version (ctx, sv, show_version_no_cb, &called)))
864     ;
865   ck_assert_int_eq (VAPI_OK, rv);
866   sv = vapi_alloc_show_version (ctx);
867   ck_assert_ptr_ne (NULL, sv);
868   while (VAPI_EAGAIN ==
869          (rv = vapi_show_version (ctx, sv, show_version_cb, &called)))
870     ;
871   ck_assert_int_eq (VAPI_OK, rv);
872   rv = vapi_dispatch (ctx);
873   ck_assert_int_eq (VAPI_OK, rv);
874   ck_assert_int_eq (2, called);
875 }
876
877 END_TEST;
878
879 vapi_error_e
880 no_msg_cb (struct vapi_ctx_s *ctx, void *callback_ctx,
881            vapi_error_e rv, bool is_last,
882            vapi_payload_sw_interface_details * reply)
883 {
884   int *called = callback_ctx;
885   ++*called;
886   ck_assert_int_eq (VAPI_OK, rv);
887   ck_assert_int_eq (true, is_last);
888   ck_assert_ptr_eq (NULL, reply);
889   return VAPI_OK;
890 }
891
892 START_TEST (test_no_response_2)
893 {
894   printf ("--- Simulate no response to dump message ---\n");
895   vapi_error_e rv;
896   vapi_msg_sw_interface_dump *dump = vapi_alloc_sw_interface_dump (ctx);
897   dump->header._vl_msg_id = ~0; /* malformed ID causes vpp to drop the msg */
898   int no_called = 0;
899   while (VAPI_EAGAIN ==
900          (rv = vapi_sw_interface_dump (ctx, dump, no_msg_cb, &no_called)))
901     ;
902   ck_assert_int_eq (VAPI_OK, rv);
903   rv = vapi_dispatch (ctx);
904   ck_assert_int_eq (VAPI_OK, rv);
905   ck_assert_int_eq (1, no_called);
906 }
907
908 END_TEST;
909
910 START_TEST (test_unsupported)
911 {
912   printf ("--- Unsupported messages ---\n");
913   bool available = vapi_is_msg_available (ctx, vapi_msg_id_test_fake_msg);
914   ck_assert_int_eq (false, available);
915 }
916
917 END_TEST;
918
919 Suite *
920 test_suite (void)
921 {
922   Suite *s = suite_create ("VAPI test");
923
924   TCase *tc_negative = tcase_create ("Negative tests");
925   tcase_add_test (tc_negative, test_invalid_values);
926   suite_add_tcase (s, tc_negative);
927
928   TCase *tc_swap = tcase_create ("Byteswap tests");
929   tcase_add_test (tc_swap, test_hton_1);
930   tcase_add_test (tc_swap, test_hton_2);
931   tcase_add_test (tc_swap, test_hton_4);
932   tcase_add_test (tc_swap, test_ntoh_1);
933   tcase_add_test (tc_swap, test_ntoh_2);
934   tcase_add_test (tc_swap, test_ntoh_4);
935   suite_add_tcase (s, tc_swap);
936
937   TCase *tc_connect = tcase_create ("Connect");
938   tcase_add_test (tc_connect, test_connect);
939   suite_add_tcase (s, tc_connect);
940
941   TCase *tc_block = tcase_create ("Blocking API");
942   tcase_set_timeout (tc_block, 25);
943   tcase_add_checked_fixture (tc_block, setup_blocking, teardown);
944   tcase_add_test (tc_block, test_show_version_1);
945   tcase_add_test (tc_block, test_show_version_2);
946   tcase_add_test (tc_block, test_loopbacks_1);
947   suite_add_tcase (s, tc_block);
948
949   TCase *tc_nonblock = tcase_create ("Nonblocking API");
950   tcase_set_timeout (tc_nonblock, 25);
951   tcase_add_checked_fixture (tc_nonblock, setup_nonblocking, teardown);
952   tcase_add_test (tc_nonblock, test_show_version_3);
953   tcase_add_test (tc_nonblock, test_show_version_4);
954   tcase_add_test (tc_nonblock, test_show_version_5);
955   tcase_add_test (tc_nonblock, test_loopbacks_2);
956   tcase_add_test (tc_nonblock, test_no_response_1);
957   tcase_add_test (tc_nonblock, test_no_response_2);
958   suite_add_tcase (s, tc_nonblock);
959
960   TCase *tc_unsupported = tcase_create ("Unsupported message");
961   tcase_add_checked_fixture (tc_unsupported, setup_blocking, teardown);
962   tcase_add_test (tc_unsupported, test_unsupported);
963   suite_add_tcase (s, tc_unsupported);
964
965   return s;
966 }
967
968 int
969 main (int argc, char *argv[])
970 {
971   if (3 != argc)
972     {
973       printf ("Invalid argc==`%d'\n", argc);
974       return EXIT_FAILURE;
975     }
976   app_name = argv[1];
977   api_prefix = argv[2];
978   printf ("App name: `%s', API prefix: `%s'\n", app_name, api_prefix);
979
980   int number_failed;
981   Suite *s;
982   SRunner *sr;
983
984   s = test_suite ();
985   sr = srunner_create (s);
986
987   srunner_run_all (sr, CK_NORMAL);
988   number_failed = srunner_ntests_failed (sr);
989   srunner_free (sr);
990   return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
991 }
992
993 /*
994  * fd.io coding-style-patch-verification: ON
995  *
996  * Local Variables:
997  * eval: (c-set-style "gnu")
998  * End:
999  */