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