LCOV - code coverage report
Current view: top level - vpp-api/vapi - vapi_cpp_test.cpp (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 223 225 99.1 %
Date: 2023-07-05 22:20:52 Functions: 18 18 100.0 %

          Line data    Source code
       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 <memory>
      19             : #include <stdio.h>
      20             : #include <unistd.h>
      21             : #include <assert.h>
      22             : #include <setjmp.h>
      23             : #include <check.h>
      24             : #include <vapi/memclnt.api.vapi.h>
      25             : #include <vapi/vapi.hpp>
      26             : #include <vapi/vpe.api.vapi.hpp>
      27             : #include <vapi/interface.api.vapi.hpp>
      28             : #include <fake.api.vapi.hpp>
      29             : 
      30             : DEFINE_VAPI_MSG_IDS_VPE_API_JSON;
      31             : DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON;
      32             : DEFINE_VAPI_MSG_IDS_FAKE_API_JSON;
      33             : 
      34             : static char *app_name = nullptr;
      35             : static char *api_prefix = nullptr;
      36             : static const int max_outstanding_requests = 32;
      37             : static const int response_queue_size = 32;
      38             : 
      39             : #define WAIT_FOR_RESPONSE(param, ret)      \
      40             :   do                                       \
      41             :     {                                      \
      42             :       ret = con.wait_for_response (param); \
      43             :     }                                      \
      44             :   while (ret == VAPI_EAGAIN)
      45             : 
      46             : using namespace vapi;
      47             : 
      48           2 : void verify_show_version_reply (const Show_version_reply &r)
      49             : {
      50           2 :   auto &p = r.get_payload ();
      51           2 :   printf ("show_version_reply: program: `%s', version: `%s', build directory: "
      52             :           "`%s', build date: `%s'\n",
      53           2 :           p.program, p.version, p.build_directory, p.build_date);
      54           2 :   ck_assert_str_eq ("vpe", (char *)p.program);
      55           2 : }
      56             : 
      57             : Connection con;
      58             : 
      59           5 : void setup (void)
      60             : {
      61           5 :   vapi_error_e rv = con.connect (
      62             :       app_name, api_prefix, max_outstanding_requests, response_queue_size);
      63           5 :   ck_assert_int_eq (VAPI_OK, rv);
      64           5 : }
      65             : 
      66           5 : void teardown (void)
      67             : {
      68           5 :   con.disconnect ();
      69           5 : }
      70             : 
      71           1 : START_TEST (test_show_version_1)
      72             : {
      73           1 :   printf ("--- Show version by reading response associated to request ---\n");
      74           2 :   Show_version sv (con);
      75           1 :   vapi_error_e rv = sv.execute ();
      76           1 :   ck_assert_int_eq (VAPI_OK, rv);
      77           1 :   WAIT_FOR_RESPONSE (sv, rv);
      78           1 :   ck_assert_int_eq (VAPI_OK, rv);
      79           1 :   auto &r = sv.get_response ();
      80           1 :   verify_show_version_reply (r);
      81             : }
      82             : 
      83           1 : END_TEST;
      84             : 
      85             : struct Show_version_cb
      86             : {
      87           1 :   Show_version_cb () : called{0} {};
      88             :   int called;
      89           1 :   vapi_error_e operator() (Show_version &sv)
      90             :   {
      91           1 :     auto &r = sv.get_response ();
      92           1 :     verify_show_version_reply (r);
      93           1 :     ++called;
      94           1 :     return VAPI_OK;
      95             :   }
      96             : };
      97             : 
      98           1 : START_TEST (test_show_version_2)
      99             : {
     100           1 :   printf ("--- Show version by getting a callback ---\n");
     101           1 :   Show_version_cb cb;
     102           2 :   Show_version sv (con, std::ref (cb));
     103           1 :   vapi_error_e rv = sv.execute ();
     104           1 :   ck_assert_int_eq (VAPI_OK, rv);
     105           1 :   con.dispatch (sv);
     106           1 :   ck_assert_int_eq (1, cb.called);
     107             : }
     108             : 
     109           1 : END_TEST;
     110             : 
     111           1 : START_TEST (test_loopbacks_1)
     112             : {
     113           1 :   printf ("--- Create/delete loopbacks by waiting for response ---\n");
     114           1 :   const auto num_ifs = 5;
     115             :   u8 mac_addresses[num_ifs][6];
     116           1 :   memset (&mac_addresses, 0, sizeof (mac_addresses));
     117             :   u32 sw_if_indexes[num_ifs];
     118           1 :   memset (&sw_if_indexes, 0xff, sizeof (sw_if_indexes));
     119           6 :   for (int i = 0; i < num_ifs; ++i)
     120             :     {
     121           5 :       memcpy (&mac_addresses[i], "\1\2\3\4\5\6", 6);
     122           5 :       mac_addresses[i][5] = i;
     123             :     }
     124           6 :   for (int i = 0; i < num_ifs; ++i)
     125             :     {
     126           5 :       Create_loopback cl (con);
     127           5 :       auto &p = cl.get_request ().get_payload ();
     128           5 :       memcpy (p.mac_address, mac_addresses[i], sizeof (p.mac_address));
     129           5 :       auto e = cl.execute ();
     130           5 :       ck_assert_int_eq (VAPI_OK, e);
     131             :       vapi_error_e rv;
     132           5 :       WAIT_FOR_RESPONSE (cl, rv);
     133           5 :       ck_assert_int_eq (VAPI_OK, rv);
     134           5 :       auto &rp = cl.get_response ().get_payload ();
     135           5 :       ck_assert_int_eq (0, rp.retval);
     136           5 :       sw_if_indexes[i] = rp.sw_if_index;
     137             :     }
     138           6 :   for (int i = 0; i < num_ifs; ++i)
     139             :     {
     140           5 :       printf ("Created loopback with MAC %02x:%02x:%02x:%02x:%02x:%02x --> "
     141             :               "sw_if_index %u\n",
     142           5 :               mac_addresses[i][0], mac_addresses[i][1], mac_addresses[i][2],
     143           5 :               mac_addresses[i][3], mac_addresses[i][4], mac_addresses[i][5],
     144             :               sw_if_indexes[i]);
     145             :     }
     146             : 
     147             :   { // new context
     148           1 :     bool seen[num_ifs] = {0};
     149           2 :     Sw_interface_dump d (con);
     150           1 :     auto rv = d.execute ();
     151           1 :     ck_assert_int_eq (VAPI_OK, rv);
     152           1 :     WAIT_FOR_RESPONSE (d, rv);
     153           1 :     ck_assert_int_eq (VAPI_OK, rv);
     154           1 :     auto &rs = d.get_result_set ();
     155           7 :     for (auto &r : rs)
     156             :       {
     157           6 :         auto &p = r.get_payload ();
     158          36 :         for (int i = 0; i < num_ifs; ++i)
     159             :           {
     160          30 :             if (sw_if_indexes[i] == p.sw_if_index)
     161             :               {
     162           5 :                 ck_assert_int_eq (0, seen[i]);
     163           5 :                 seen[i] = true;
     164             :               }
     165             :           }
     166             :       }
     167           6 :     for (int i = 0; i < num_ifs; ++i)
     168             :       {
     169           5 :         ck_assert_int_eq (1, seen[i]);
     170             :       }
     171             :   }
     172             : 
     173           6 :   for (int i = 0; i < num_ifs; ++i)
     174             :     {
     175          10 :       Delete_loopback dl (con);
     176           5 :       dl.get_request ().get_payload ().sw_if_index = sw_if_indexes[i];
     177           5 :       auto rv = dl.execute ();
     178           5 :       ck_assert_int_eq (VAPI_OK, rv);
     179           5 :       WAIT_FOR_RESPONSE (dl, rv);
     180           5 :       ck_assert_int_eq (VAPI_OK, rv);
     181           5 :       auto &response = dl.get_response ();
     182           5 :       auto rp = response.get_payload ();
     183           5 :       ck_assert_int_eq (0, rp.retval);
     184           5 :       printf ("Deleted loopback with sw_if_index %u\n", sw_if_indexes[i]);
     185             :     }
     186             : 
     187             :   { // new context
     188           2 :     Sw_interface_dump d (con);
     189           1 :     auto rv = d.execute ();
     190           1 :     ck_assert_int_eq (VAPI_OK, rv);
     191           1 :     WAIT_FOR_RESPONSE (d, rv);
     192           1 :     ck_assert_int_eq (VAPI_OK, rv);
     193           1 :     auto &rs = d.get_result_set ();
     194           2 :     for (auto &r : rs)
     195             :       {
     196           1 :         auto &p = r.get_payload ();
     197           6 :         for (int i = 0; i < num_ifs; ++i)
     198             :           {
     199           5 :             ck_assert_int_ne (sw_if_indexes[i], p.sw_if_index);
     200             :           }
     201             :       }
     202             :   }
     203             : }
     204             : 
     205           1 : END_TEST;
     206             : 
     207             : struct Create_loopback_cb
     208             : {
     209           5 :   Create_loopback_cb () : called{ 0 }, sw_if_index{ 0 }, seen{ false } {};
     210             :   int called;
     211             :   u32 sw_if_index;
     212             :   bool seen;
     213           5 :   vapi_error_e operator() (Create_loopback &cl)
     214             :   {
     215           5 :     auto &r = cl.get_response ();
     216           5 :     sw_if_index = r.get_payload ().sw_if_index;
     217           5 :     ++called;
     218           5 :     return VAPI_OK;
     219             :   }
     220             : };
     221             : 
     222             : struct Delete_loopback_cb
     223             : {
     224           5 :   Delete_loopback_cb () : called{ 0 }, sw_if_index{ 0 }, seen{ false } {};
     225             :   int called;
     226             :   u32 sw_if_index;
     227             :   bool seen;
     228           5 :   vapi_error_e operator() (Delete_loopback &dl)
     229             :   {
     230           5 :     auto &r = dl.get_response ();
     231           5 :     ck_assert_int_eq (0, r.get_payload ().retval);
     232           5 :     ++called;
     233           5 :     return VAPI_OK;
     234             :   }
     235             : };
     236             : 
     237             : template <int num_ifs> struct Sw_interface_dump_cb
     238             : {
     239           1 :   Sw_interface_dump_cb (std::array<Create_loopback_cb, num_ifs> &cbs)
     240           1 :       : called{0}, cbs{cbs} {};
     241             :   int called;
     242             :   std::array<Create_loopback_cb, num_ifs> &cbs;
     243           1 :   vapi_error_e operator() (Sw_interface_dump &d)
     244             :   {
     245           6 :     for (auto &y : cbs)
     246             :       {
     247           5 :         y.seen = false;
     248             :       }
     249           7 :     for (auto &x : d.get_result_set ())
     250             :       {
     251           6 :         auto &p = x.get_payload ();
     252          36 :         for (auto &y : cbs)
     253             :           {
     254          30 :             if (p.sw_if_index == y.sw_if_index)
     255             :               {
     256           5 :                 y.seen = true;
     257             :               }
     258             :           }
     259             :       }
     260           6 :     for (auto &y : cbs)
     261             :       {
     262           5 :         ck_assert_int_eq (true, y.seen);
     263             :       }
     264           1 :     ++called;
     265           1 :     return VAPI_OK;
     266             :   }
     267             : };
     268             : 
     269           1 : START_TEST (test_loopbacks_2)
     270             : {
     271           1 :   printf ("--- Create/delete loopbacks by getting a callback ---\n");
     272           1 :   const auto num_ifs = 5;
     273             :   u8 mac_addresses[num_ifs][6];
     274           1 :   memset (&mac_addresses, 0, sizeof (mac_addresses));
     275           6 :   for (int i = 0; i < num_ifs; ++i)
     276             :     {
     277           5 :       memcpy (&mac_addresses[i], "\1\2\3\4\5\6", 6);
     278           5 :       mac_addresses[i][5] = i;
     279             :     }
     280           1 :   std::array<Create_loopback_cb, num_ifs> ccbs;
     281           5 :   std::array<std::unique_ptr<Create_loopback>, num_ifs> clcs;
     282           6 :   for (int i = 0; i < num_ifs; ++i)
     283             :     {
     284           5 :       Create_loopback *cl = new Create_loopback (con, std::ref (ccbs[i]));
     285           5 :       clcs[i].reset (cl);
     286           5 :       auto &p = cl->get_request ().get_payload ();
     287           5 :       memcpy (p.mac_address, mac_addresses[i], sizeof (p.mac_address));
     288           5 :       auto e = cl->execute ();
     289           5 :       ck_assert_int_eq (VAPI_OK, e);
     290             :     }
     291           1 :   con.dispatch ();
     292           6 :   for (int i = 0; i < num_ifs; ++i)
     293             :     {
     294           5 :       ck_assert_int_eq (1, ccbs[i].called);
     295           5 :       printf ("Created loopback with MAC %02x:%02x:%02x:%02x:%02x:%02x --> "
     296             :               "sw_if_index %u\n",
     297           5 :               mac_addresses[i][0], mac_addresses[i][1], mac_addresses[i][2],
     298           5 :               mac_addresses[i][3], mac_addresses[i][4], mac_addresses[i][5],
     299           5 :               ccbs[i].sw_if_index);
     300             :     }
     301             : 
     302           1 :   Sw_interface_dump_cb<num_ifs> swdcb (ccbs);
     303           2 :   Sw_interface_dump d (con, std::ref (swdcb));
     304           1 :   auto rv = d.execute ();
     305           1 :   ck_assert_int_eq (VAPI_OK, rv);
     306           1 :   WAIT_FOR_RESPONSE (d, rv);
     307           1 :   ck_assert_int_eq (VAPI_OK, rv);
     308           1 :   ck_assert_int_ne (0, swdcb.called);
     309           1 :   std::array<Delete_loopback_cb, num_ifs> dcbs;
     310           5 :   std::array<std::unique_ptr<Delete_loopback>, num_ifs> dlcs;
     311           6 :   for (int i = 0; i < num_ifs; ++i)
     312             :     {
     313           5 :       Delete_loopback *dl = new Delete_loopback (con, std::ref (dcbs[i]));
     314           5 :       dlcs[i].reset (dl);
     315           5 :       auto &p = dl->get_request ().get_payload ();
     316           5 :       p.sw_if_index = ccbs[i].sw_if_index;
     317           5 :       dcbs[i].sw_if_index = ccbs[i].sw_if_index;
     318           5 :       auto e = dl->execute ();
     319           5 :       ck_assert_int_eq (VAPI_OK, e);
     320             :     }
     321           1 :   con.dispatch ();
     322           6 :   for (auto &x : dcbs)
     323             :     {
     324           5 :       ck_assert_int_eq (true, x.called);
     325           5 :       printf ("Deleted loopback with sw_if_index %u\n", x.sw_if_index);
     326             :     }
     327             : 
     328             :   { // new context
     329           2 :     Sw_interface_dump d (con);
     330           1 :     auto rv = d.execute ();
     331           1 :     ck_assert_int_eq (VAPI_OK, rv);
     332           1 :     WAIT_FOR_RESPONSE (d, rv);
     333           1 :     ck_assert_int_eq (VAPI_OK, rv);
     334           1 :     auto &rs = d.get_result_set ();
     335           2 :     for (auto &r : rs)
     336             :       {
     337           1 :         auto &p = r.get_payload ();
     338           6 :         for (int i = 0; i < num_ifs; ++i)
     339             :           {
     340           5 :             ck_assert_int_ne (ccbs[i].sw_if_index, p.sw_if_index);
     341             :           }
     342             :       }
     343             :   }
     344             : }
     345             : 
     346           1 : END_TEST;
     347             : 
     348           1 : START_TEST (test_unsupported)
     349             : {
     350           1 :   printf ("--- Unsupported messages ---\n");
     351           1 :   bool thrown = false;
     352             :   try
     353             :     {
     354           2 :       Test_fake_msg fake (con);
     355             :     }
     356           2 :   catch (const Msg_not_available_exception &)
     357             :     {
     358           1 :       thrown = true;
     359           1 :       printf ("Constructing unsupported msg not possible - test pass.\n");
     360             :     }
     361           1 :   ck_assert_int_eq (true, thrown);
     362           1 :   thrown = false;
     363             :   try
     364             :     {
     365           2 :       Test_fake_dump fake (con);
     366             :     }
     367           2 :   catch (const Msg_not_available_exception &)
     368             :     {
     369           1 :       thrown = true;
     370           1 :       printf ("Constructing unsupported dump not possible - test pass.\n");
     371             :     }
     372           1 :   ck_assert_int_eq (true, thrown);
     373           1 :   thrown = false;
     374             :   try
     375             :     {
     376           2 :       Event_registration<Test_fake_details> fake (con);
     377             :     }
     378           2 :   catch (const Msg_not_available_exception &)
     379             :     {
     380           1 :       thrown = true;
     381           1 :       printf ("Constructing unsupported event registration not possible - "
     382             :               "test pass.\n");
     383             :     }
     384           1 :   ck_assert_int_eq (true, thrown);
     385             : }
     386             : 
     387           1 : END_TEST;
     388             : 
     389           6 : Suite *test_suite (void)
     390             : {
     391           6 :   Suite *s = suite_create ("VAPI test");
     392             : 
     393           6 :   TCase *tc_cpp_api = tcase_create ("C++ API");
     394           6 :   tcase_set_timeout (tc_cpp_api, 25);
     395           6 :   tcase_add_checked_fixture (tc_cpp_api, setup, teardown);
     396           6 :   tcase_add_test (tc_cpp_api, test_show_version_1);
     397           6 :   tcase_add_test (tc_cpp_api, test_show_version_2);
     398           6 :   tcase_add_test (tc_cpp_api, test_loopbacks_1);
     399           6 :   tcase_add_test (tc_cpp_api, test_loopbacks_2);
     400           6 :   tcase_add_test (tc_cpp_api, test_unsupported);
     401           6 :   suite_add_tcase (s, tc_cpp_api);
     402             : 
     403           6 :   return s;
     404             : }
     405             : 
     406           6 : int main (int argc, char *argv[])
     407             : {
     408           6 :   if (3 != argc)
     409             :     {
     410           0 :       printf ("Invalid argc==`%d'\n", argc);
     411           0 :       return EXIT_FAILURE;
     412             :     }
     413           6 :   app_name = argv[1];
     414           6 :   api_prefix = argv[2];
     415           6 :   printf ("App name: `%s', API prefix: `%s'\n", app_name, api_prefix);
     416             : 
     417             :   int number_failed;
     418             :   Suite *s;
     419             :   SRunner *sr;
     420             : 
     421           6 :   s = test_suite ();
     422           6 :   sr = srunner_create (s);
     423             : 
     424           6 :   srunner_run_all (sr, CK_NORMAL);
     425           1 :   number_failed = srunner_ntests_failed (sr);
     426           1 :   srunner_free (sr);
     427           1 :   return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
     428             : }
     429             : 
     430             : /*
     431             :  * fd.io coding-style-patch-verification: ON
     432             :  *
     433             :  * Local Variables:
     434             :  * eval: (c-set-style "gnu")
     435             :  * End:
     436             :  */

Generated by: LCOV version 1.14