a9572ae87163cc1d778d078914ce684d071dddaa
[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 *) p->program);
363   printf
364     ("show_version_reply: program: `%s', version: `%s', build directory: "
365      "`%s', build date: `%s'\n", p->program, p->version, p->build_directory,
366      p->build_date);
367   ++*(int *) caller_ctx;
368   return VAPI_OK;
369 }
370
371 typedef struct
372 {
373   int called;
374   int expected_retval;
375   u32 *sw_if_index_storage;
376 } test_create_loopback_ctx_t;
377
378 vapi_error_e
379 loopback_create_cb (vapi_ctx_t ctx, void *caller_ctx,
380                     vapi_error_e rv, bool is_last,
381                     vapi_payload_create_loopback_reply * p)
382 {
383   test_create_loopback_ctx_t *clc = caller_ctx;
384   ck_assert_int_eq (clc->expected_retval, p->retval);
385   *clc->sw_if_index_storage = p->sw_if_index;
386   ++clc->called;
387   return VAPI_OK;
388 }
389
390 typedef struct
391 {
392   int called;
393   int expected_retval;
394   u32 *sw_if_index_storage;
395 } test_delete_loopback_ctx_t;
396
397 vapi_error_e
398 loopback_delete_cb (vapi_ctx_t ctx, void *caller_ctx,
399                     vapi_error_e rv, bool is_last,
400                     vapi_payload_delete_loopback_reply * p)
401 {
402   test_delete_loopback_ctx_t *dlc = caller_ctx;
403   ck_assert_int_eq (dlc->expected_retval, p->retval);
404   ++dlc->called;
405   return VAPI_OK;
406 }
407
408 START_TEST (test_connect)
409 {
410   vapi_ctx_t ctx;
411   vapi_error_e rv = vapi_ctx_alloc (&ctx);
412   ck_assert_int_eq (VAPI_OK, rv);
413   rv = vapi_connect (ctx, app_name, api_prefix, max_outstanding_requests,
414                      response_queue_size, VAPI_MODE_BLOCKING, true);
415   ck_assert_int_eq (VAPI_OK, rv);
416   rv = vapi_disconnect (ctx);
417   ck_assert_int_eq (VAPI_OK, rv);
418   vapi_ctx_free (ctx);
419 }
420
421 END_TEST;
422
423 vapi_ctx_t ctx;
424
425 void
426 setup_blocking (void)
427 {
428   vapi_error_e rv = vapi_ctx_alloc (&ctx);
429   ck_assert_int_eq (VAPI_OK, rv);
430   rv = vapi_connect (ctx, app_name, api_prefix, max_outstanding_requests,
431                      response_queue_size, VAPI_MODE_BLOCKING, true);
432   ck_assert_int_eq (VAPI_OK, rv);
433 }
434
435 void
436 setup_nonblocking (void)
437 {
438   vapi_error_e rv = vapi_ctx_alloc (&ctx);
439   ck_assert_int_eq (VAPI_OK, rv);
440   rv = vapi_connect (ctx, app_name, api_prefix, max_outstanding_requests,
441                      response_queue_size, VAPI_MODE_NONBLOCKING, true);
442   ck_assert_int_eq (VAPI_OK, rv);
443 }
444
445 void
446 teardown (void)
447 {
448   vapi_disconnect (ctx);
449   vapi_ctx_free (ctx);
450 }
451
452 START_TEST (test_show_version_1)
453 {
454   printf ("--- Basic show version message - reply test ---\n");
455   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
456   ck_assert_ptr_ne (NULL, sv);
457   vapi_msg_show_version_hton (sv);
458   vapi_error_e rv = vapi_send (ctx, sv);
459   ck_assert_int_eq (VAPI_OK, rv);
460   vapi_msg_show_version_reply *resp;
461   size_t size;
462   rv = vapi_recv (ctx, (void *) &resp, &size, 0, 0);
463   ck_assert_int_eq (VAPI_OK, rv);
464   int dummy;
465   show_version_cb (NULL, &dummy, VAPI_OK, true, &resp->payload);
466   vapi_msg_free (ctx, resp);
467 }
468
469 END_TEST;
470
471 START_TEST (test_show_version_2)
472 {
473   int called = 0;
474   printf ("--- Show version via blocking callback API ---\n");
475   const int attempts = response_queue_size * 4;
476   int i = 0;
477   for (i = 0; i < attempts; ++i)
478     {
479       vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
480       ck_assert_ptr_ne (NULL, sv);
481       vapi_error_e rv = vapi_show_version (ctx, sv, show_version_cb, &called);
482       ck_assert_int_eq (VAPI_OK, rv);
483     }
484   ck_assert_int_eq (attempts, called);
485 }
486
487 END_TEST;
488
489 typedef struct
490 {
491   bool last_called;
492   size_t num_ifs;
493   u32 *sw_if_indexes;
494   bool *seen;
495   int called;
496 } sw_interface_dump_ctx;
497
498 vapi_error_e
499 sw_interface_dump_cb (struct vapi_ctx_s *ctx, void *callback_ctx,
500                       vapi_error_e rv, bool is_last,
501                       vapi_payload_sw_interface_details * reply)
502 {
503   sw_interface_dump_ctx *dctx = callback_ctx;
504   ck_assert_int_eq (false, dctx->last_called);
505   if (is_last)
506     {
507       ck_assert (NULL == reply);
508       dctx->last_called = true;
509     }
510   else
511     {
512       ck_assert (NULL != reply);
513       printf ("Interface dump entry: [%u]: %s\n", reply->sw_if_index,
514               reply->interface_name);
515       size_t i = 0;
516       for (i = 0; i < dctx->num_ifs; ++i)
517         {
518           if (dctx->sw_if_indexes[i] == reply->sw_if_index)
519             {
520               ck_assert_int_eq (false, dctx->seen[i]);
521               dctx->seen[i] = true;
522             }
523         }
524     }
525   ++dctx->called;
526   return VAPI_OK;
527 }
528
529 START_TEST (test_loopbacks_1)
530 {
531   printf ("--- Create/delete loopbacks using blocking API ---\n");
532   const size_t num_ifs = 5;
533   u8 mac_addresses[num_ifs][6];
534   clib_memset (&mac_addresses, 0, sizeof (mac_addresses));
535   u32 sw_if_indexes[num_ifs];
536   clib_memset (&sw_if_indexes, 0xff, sizeof (sw_if_indexes));
537   test_create_loopback_ctx_t clcs[num_ifs];
538   clib_memset (&clcs, 0, sizeof (clcs));
539   test_delete_loopback_ctx_t dlcs[num_ifs];
540   clib_memset (&dlcs, 0, sizeof (dlcs));
541   int i;
542   for (i = 0; i < num_ifs; ++i)
543     {
544       memcpy (&mac_addresses[i], "\1\2\3\4\5\6", 6);
545       mac_addresses[i][5] = i;
546       clcs[i].sw_if_index_storage = &sw_if_indexes[i];
547     }
548   for (i = 0; i < num_ifs; ++i)
549     {
550       vapi_msg_create_loopback *cl = vapi_alloc_create_loopback (ctx);
551       memcpy (cl->payload.mac_address, mac_addresses[i],
552               sizeof (cl->payload.mac_address));
553       vapi_error_e rv =
554         vapi_create_loopback (ctx, cl, loopback_create_cb, &clcs[i]);
555       ck_assert_int_eq (VAPI_OK, rv);
556     }
557   for (i = 0; i < num_ifs; ++i)
558     {
559       ck_assert_int_eq (1, clcs[i].called);
560       printf ("Created loopback with MAC %02x:%02x:%02x:%02x:%02x:%02x --> "
561               "sw_if_index %u\n",
562               mac_addresses[i][0], mac_addresses[i][1], mac_addresses[i][2],
563               mac_addresses[i][3], mac_addresses[i][4], mac_addresses[i][5],
564               sw_if_indexes[i]);
565     }
566   bool seen[num_ifs];
567   sw_interface_dump_ctx dctx = { false, num_ifs, sw_if_indexes, seen, 0 };
568   vapi_msg_sw_interface_dump *dump;
569   vapi_error_e rv;
570   const int attempts = response_queue_size * 4;
571   for (i = 0; i < attempts; ++i)
572     {
573       dctx.last_called = false;
574       clib_memset (&seen, 0, sizeof (seen));
575       dump = vapi_alloc_sw_interface_dump (ctx);
576       dump->payload.name_filter_valid = 0;
577       clib_memset (dump->payload.name_filter.buf, 0,
578                    dump->payload.name_filter.length);
579       while (VAPI_EAGAIN ==
580              (rv =
581               vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb,
582                                       &dctx)))
583         ;
584       ck_assert_int_eq (true, dctx.last_called);
585       int j = 0;
586       for (j = 0; j < num_ifs; ++j)
587         {
588           ck_assert_int_eq (true, seen[j]);
589         }
590     }
591   clib_memset (&seen, 0, sizeof (seen));
592   for (i = 0; i < num_ifs; ++i)
593     {
594       vapi_msg_delete_loopback *dl = vapi_alloc_delete_loopback (ctx);
595       dl->payload.sw_if_index = sw_if_indexes[i];
596       vapi_error_e rv =
597         vapi_delete_loopback (ctx, dl, loopback_delete_cb, &dlcs[i]);
598       ck_assert_int_eq (VAPI_OK, rv);
599     }
600   for (i = 0; i < num_ifs; ++i)
601     {
602       ck_assert_int_eq (1, dlcs[i].called);
603       printf ("Deleted loopback with sw_if_index %u\n", sw_if_indexes[i]);
604     }
605   dctx.last_called = false;
606   clib_memset (&seen, 0, sizeof (seen));
607   dump = vapi_alloc_sw_interface_dump (ctx);
608   dump->payload.name_filter_valid = 0;
609   clib_memset (dump->payload.name_filter.buf, 0,
610                dump->payload.name_filter.length);
611   while (VAPI_EAGAIN ==
612          (rv =
613           vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb, &dctx)))
614     ;
615   ck_assert_int_eq (true, dctx.last_called);
616   for (i = 0; i < num_ifs; ++i)
617     {
618       ck_assert_int_eq (false, seen[i]);
619     }
620 }
621
622 END_TEST;
623
624 START_TEST (test_show_version_3)
625 {
626   printf ("--- Show version via async callback ---\n");
627   int called = 0;
628   vapi_error_e rv;
629   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
630   ck_assert_ptr_ne (NULL, sv);
631   while (VAPI_EAGAIN ==
632          (rv = vapi_show_version (ctx, sv, show_version_cb, &called)))
633     ;
634   ck_assert_int_eq (VAPI_OK, rv);
635   ck_assert_int_eq (0, called);
636   rv = vapi_dispatch (ctx);
637   ck_assert_int_eq (VAPI_OK, rv);
638   ck_assert_int_eq (1, called);
639   called = 0;
640   rv = vapi_dispatch (ctx);
641   ck_assert_int_eq (VAPI_OK, rv);
642   ck_assert_int_eq (0, called);
643 }
644
645 END_TEST;
646
647 START_TEST (test_show_version_4)
648 {
649   printf ("--- Show version via async callback - multiple messages ---\n");
650   vapi_error_e rv;
651   const size_t num_req = 5;
652   int contexts[num_req];
653   clib_memset (contexts, 0, sizeof (contexts));
654   int i;
655   for (i = 0; i < num_req; ++i)
656     {
657       vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
658       ck_assert_ptr_ne (NULL, sv);
659       while (VAPI_EAGAIN ==
660              (rv =
661               vapi_show_version (ctx, sv, show_version_cb, &contexts[i])))
662         ;
663       ck_assert_int_eq (VAPI_OK, rv);
664       int j;
665       for (j = 0; j < num_req; ++j)
666         {
667           ck_assert_int_eq (0, contexts[j]);
668         }
669     }
670   rv = vapi_dispatch (ctx);
671   ck_assert_int_eq (VAPI_OK, rv);
672   for (i = 0; i < num_req; ++i)
673     {
674       ck_assert_int_eq (1, contexts[i]);
675     }
676   clib_memset (contexts, 0, sizeof (contexts));
677   rv = vapi_dispatch (ctx);
678   ck_assert_int_eq (VAPI_OK, rv);
679   for (i = 0; i < num_req; ++i)
680     {
681       ck_assert_int_eq (0, contexts[i]);
682     }
683 }
684
685 END_TEST;
686
687 START_TEST (test_loopbacks_2)
688 {
689   printf ("--- Create/delete loopbacks using non-blocking API ---\n");
690   vapi_error_e rv;
691   const size_t num_ifs = 5;
692   u8 mac_addresses[num_ifs][6];
693   clib_memset (&mac_addresses, 0, sizeof (mac_addresses));
694   u32 sw_if_indexes[num_ifs];
695   clib_memset (&sw_if_indexes, 0xff, sizeof (sw_if_indexes));
696   test_create_loopback_ctx_t clcs[num_ifs];
697   clib_memset (&clcs, 0, sizeof (clcs));
698   test_delete_loopback_ctx_t dlcs[num_ifs];
699   clib_memset (&dlcs, 0, sizeof (dlcs));
700   int i;
701   for (i = 0; i < num_ifs; ++i)
702     {
703       memcpy (&mac_addresses[i], "\1\2\3\4\5\6", 6);
704       mac_addresses[i][5] = i;
705       clcs[i].sw_if_index_storage = &sw_if_indexes[i];
706     }
707   for (i = 0; i < num_ifs; ++i)
708     {
709       vapi_msg_create_loopback *cl = vapi_alloc_create_loopback (ctx);
710       memcpy (cl->payload.mac_address, mac_addresses[i],
711               sizeof (cl->payload.mac_address));
712       while (VAPI_EAGAIN ==
713              (rv =
714               vapi_create_loopback (ctx, cl, loopback_create_cb, &clcs[i])))
715         ;
716       ck_assert_int_eq (VAPI_OK, rv);
717     }
718   rv = vapi_dispatch (ctx);
719   ck_assert_int_eq (VAPI_OK, rv);
720   for (i = 0; i < num_ifs; ++i)
721     {
722       ck_assert_int_eq (1, clcs[i].called);
723       printf ("Loopback with MAC %02x:%02x:%02x:%02x:%02x:%02x --> "
724               "sw_if_index %u\n",
725               mac_addresses[i][0], mac_addresses[i][1], mac_addresses[i][2],
726               mac_addresses[i][3], mac_addresses[i][4], mac_addresses[i][5],
727               sw_if_indexes[i]);
728     }
729   bool seen[num_ifs];
730   clib_memset (&seen, 0, sizeof (seen));
731   sw_interface_dump_ctx dctx = { false, num_ifs, sw_if_indexes, seen, 0 };
732   vapi_msg_sw_interface_dump *dump = vapi_alloc_sw_interface_dump (ctx);
733   dump->payload.name_filter_valid = 0;
734   clib_memset (dump->payload.name_filter.buf, 0,
735                dump->payload.name_filter.length);
736   while (VAPI_EAGAIN ==
737          (rv =
738           vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb, &dctx)))
739     ;
740   for (i = 0; i < num_ifs; ++i)
741     {
742       ck_assert_int_eq (false, seen[i]);
743     }
744   clib_memset (&seen, 0, sizeof (seen));
745   ck_assert_int_eq (false, dctx.last_called);
746   rv = vapi_dispatch (ctx);
747   ck_assert_int_eq (VAPI_OK, rv);
748   for (i = 0; i < num_ifs; ++i)
749     {
750       ck_assert_int_eq (true, seen[i]);
751     }
752   clib_memset (&seen, 0, sizeof (seen));
753   ck_assert_int_eq (true, dctx.last_called);
754   for (i = 0; i < num_ifs; ++i)
755     {
756       vapi_msg_delete_loopback *dl = vapi_alloc_delete_loopback (ctx);
757       dl->payload.sw_if_index = sw_if_indexes[i];
758       while (VAPI_EAGAIN ==
759              (rv =
760               vapi_delete_loopback (ctx, dl, loopback_delete_cb, &dlcs[i])))
761         ;
762       ck_assert_int_eq (VAPI_OK, rv);
763     }
764   rv = vapi_dispatch (ctx);
765   ck_assert_int_eq (VAPI_OK, rv);
766   for (i = 0; i < num_ifs; ++i)
767     {
768       ck_assert_int_eq (1, dlcs[i].called);
769       printf ("Deleted loopback with sw_if_index %u\n", sw_if_indexes[i]);
770     }
771   clib_memset (&seen, 0, sizeof (seen));
772   dctx.last_called = false;
773   dump = vapi_alloc_sw_interface_dump (ctx);
774   dump->payload.name_filter_valid = 0;
775   clib_memset (dump->payload.name_filter.buf, 0,
776                dump->payload.name_filter.length);
777   while (VAPI_EAGAIN ==
778          (rv =
779           vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb, &dctx)))
780     ;
781   rv = vapi_dispatch (ctx);
782   ck_assert_int_eq (VAPI_OK, rv);
783   for (i = 0; i < num_ifs; ++i)
784     {
785       ck_assert_int_eq (false, seen[i]);
786     }
787   clib_memset (&seen, 0, sizeof (seen));
788   ck_assert_int_eq (true, dctx.last_called);
789 }
790
791 END_TEST;
792
793 vapi_error_e
794 generic_cb (vapi_ctx_t ctx, void *callback_ctx, vapi_msg_id_t id, void *msg)
795 {
796   int *called = callback_ctx;
797   ck_assert_int_eq (0, *called);
798   ++*called;
799   ck_assert_int_eq (id, vapi_msg_id_show_version_reply);
800   ck_assert_ptr_ne (NULL, msg);
801   vapi_msg_show_version_reply *reply = msg;
802   ck_assert_str_eq ("vpe", (char *) reply->payload.program);
803   return VAPI_OK;
804 }
805
806 START_TEST (test_show_version_5)
807 {
808   printf ("--- Receive show version using generic callback - nonblocking "
809           "API ---\n");
810   vapi_error_e rv;
811   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
812   ck_assert_ptr_ne (NULL, sv);
813   vapi_msg_show_version_hton (sv);
814   while (VAPI_EAGAIN == (rv = vapi_send (ctx, sv)))
815     ;
816   ck_assert_int_eq (VAPI_OK, rv);
817   int called = 0;
818   vapi_set_generic_event_cb (ctx, generic_cb, &called);
819   ck_assert_int_eq (VAPI_OK, rv);
820   rv = vapi_dispatch_one (ctx);
821   ck_assert_int_eq (VAPI_OK, rv);
822   ck_assert_int_eq (1, called);
823   sv = vapi_alloc_show_version (ctx);
824   ck_assert_ptr_ne (NULL, sv);
825   vapi_msg_show_version_hton (sv);
826   while (VAPI_EAGAIN == (rv = vapi_send (ctx, sv)))
827     ;
828   ck_assert_int_eq (VAPI_OK, rv);
829   vapi_clear_generic_event_cb (ctx);
830   rv = vapi_dispatch_one (ctx);
831   ck_assert_int_eq (VAPI_OK, rv);
832   ck_assert_int_eq (1, called); /* needs to remain unchanged */
833 }
834
835 END_TEST;
836
837 vapi_error_e
838 show_version_no_cb (vapi_ctx_t ctx, void *caller_ctx,
839                     vapi_error_e rv, bool is_last,
840                     vapi_payload_show_version_reply * p)
841 {
842   ck_assert_int_eq (VAPI_ENORESP, rv);
843   ck_assert_int_eq (true, is_last);
844   ck_assert_ptr_eq (NULL, p);
845   ++*(int *) caller_ctx;
846   return VAPI_OK;
847 }
848
849 START_TEST (test_no_response_1)
850 {
851   printf ("--- Simulate no response to regular message ---\n");
852   vapi_error_e rv;
853   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
854   ck_assert_ptr_ne (NULL, sv);
855   sv->header._vl_msg_id = ~0;   /* malformed ID causes vpp to drop the msg */
856   int called = 0;
857   while (VAPI_EAGAIN ==
858          (rv = vapi_show_version (ctx, sv, show_version_no_cb, &called)))
859     ;
860   ck_assert_int_eq (VAPI_OK, rv);
861   sv = vapi_alloc_show_version (ctx);
862   ck_assert_ptr_ne (NULL, sv);
863   while (VAPI_EAGAIN ==
864          (rv = vapi_show_version (ctx, sv, show_version_cb, &called)))
865     ;
866   ck_assert_int_eq (VAPI_OK, rv);
867   rv = vapi_dispatch (ctx);
868   ck_assert_int_eq (VAPI_OK, rv);
869   ck_assert_int_eq (2, called);
870 }
871
872 END_TEST;
873
874 vapi_error_e
875 no_msg_cb (struct vapi_ctx_s *ctx, void *callback_ctx,
876            vapi_error_e rv, bool is_last,
877            vapi_payload_sw_interface_details * reply)
878 {
879   int *called = callback_ctx;
880   ++*called;
881   ck_assert_int_eq (VAPI_OK, rv);
882   ck_assert_int_eq (true, is_last);
883   ck_assert_ptr_eq (NULL, reply);
884   return VAPI_OK;
885 }
886
887 START_TEST (test_no_response_2)
888 {
889   printf ("--- Simulate no response to dump message ---\n");
890   vapi_error_e rv;
891   vapi_msg_sw_interface_dump *dump = vapi_alloc_sw_interface_dump (ctx);
892   dump->header._vl_msg_id = ~0; /* malformed ID causes vpp to drop the msg */
893   int no_called = 0;
894   while (VAPI_EAGAIN ==
895          (rv = vapi_sw_interface_dump (ctx, dump, no_msg_cb, &no_called)))
896     ;
897   ck_assert_int_eq (VAPI_OK, rv);
898   rv = vapi_dispatch (ctx);
899   ck_assert_int_eq (VAPI_OK, rv);
900   ck_assert_int_eq (1, no_called);
901 }
902
903 END_TEST;
904
905 START_TEST (test_unsupported)
906 {
907   printf ("--- Unsupported messages ---\n");
908   bool available = vapi_is_msg_available (ctx, vapi_msg_id_test_fake_msg);
909   ck_assert_int_eq (false, available);
910 }
911
912 END_TEST;
913
914 Suite *
915 test_suite (void)
916 {
917   Suite *s = suite_create ("VAPI test");
918
919   TCase *tc_negative = tcase_create ("Negative tests");
920   tcase_add_test (tc_negative, test_invalid_values);
921   suite_add_tcase (s, tc_negative);
922
923   TCase *tc_swap = tcase_create ("Byteswap tests");
924   tcase_add_test (tc_swap, test_hton_1);
925   tcase_add_test (tc_swap, test_hton_2);
926   tcase_add_test (tc_swap, test_hton_4);
927   tcase_add_test (tc_swap, test_ntoh_1);
928   tcase_add_test (tc_swap, test_ntoh_2);
929   tcase_add_test (tc_swap, test_ntoh_4);
930   suite_add_tcase (s, tc_swap);
931
932   TCase *tc_connect = tcase_create ("Connect");
933   tcase_add_test (tc_connect, test_connect);
934   suite_add_tcase (s, tc_connect);
935
936   TCase *tc_block = tcase_create ("Blocking API");
937   tcase_set_timeout (tc_block, 25);
938   tcase_add_checked_fixture (tc_block, setup_blocking, teardown);
939   tcase_add_test (tc_block, test_show_version_1);
940   tcase_add_test (tc_block, test_show_version_2);
941   tcase_add_test (tc_block, test_loopbacks_1);
942   suite_add_tcase (s, tc_block);
943
944   TCase *tc_nonblock = tcase_create ("Nonblocking API");
945   tcase_set_timeout (tc_nonblock, 25);
946   tcase_add_checked_fixture (tc_nonblock, setup_nonblocking, teardown);
947   tcase_add_test (tc_nonblock, test_show_version_3);
948   tcase_add_test (tc_nonblock, test_show_version_4);
949   tcase_add_test (tc_nonblock, test_show_version_5);
950   tcase_add_test (tc_nonblock, test_loopbacks_2);
951   tcase_add_test (tc_nonblock, test_no_response_1);
952   tcase_add_test (tc_nonblock, test_no_response_2);
953   suite_add_tcase (s, tc_nonblock);
954
955   TCase *tc_unsupported = tcase_create ("Unsupported message");
956   tcase_add_checked_fixture (tc_unsupported, setup_blocking, teardown);
957   tcase_add_test (tc_unsupported, test_unsupported);
958   suite_add_tcase (s, tc_unsupported);
959
960   return s;
961 }
962
963 int
964 main (int argc, char *argv[])
965 {
966   if (3 != argc)
967     {
968       printf ("Invalid argc==`%d'\n", argc);
969       return EXIT_FAILURE;
970     }
971   app_name = argv[1];
972   api_prefix = argv[2];
973   printf ("App name: `%s', API prefix: `%s'\n", app_name, api_prefix);
974
975   int number_failed;
976   Suite *s;
977   SRunner *sr;
978
979   s = test_suite ();
980   sr = srunner_create (s);
981
982   srunner_run_all (sr, CK_NORMAL);
983   number_failed = srunner_ntests_failed (sr);
984   srunner_free (sr);
985   return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
986 }
987
988 /*
989  * fd.io coding-style-patch-verification: ON
990  *
991  * Local Variables:
992  * eval: (c-set-style "gnu")
993  * End:
994  */