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