LCOV - code coverage report
Current view: top level - plugins/unittest - counter_test.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 72 84 85.7 %
Date: 2023-07-05 22:20:52 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2021 EMnify.
       3             :  *
       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             : #include <vlib/vlib.h>
      17             : #include <vppinfra/time.h>
      18             : #include <vppinfra/cache.h>
      19             : #include <vppinfra/error.h>
      20             : 
      21             : #include <vlib/counter.h>
      22             : #include <vlib/stats/stats.h>
      23             : 
      24             : enum
      25             : {
      26             :   type_simple = 0,
      27             :   type_combined,
      28             : };
      29             : 
      30             : enum
      31             : {
      32             :   test_expand = 0,
      33             : };
      34             : 
      35             : /*
      36             :  * Return the stats segment epoch value.
      37             :  */
      38             : static uint64_t
      39          39 : get_stats_epoch ()
      40             : {
      41          39 :   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
      42          39 :   return sm->shared_header->epoch;
      43             : }
      44             : 
      45             : /* number of times to repeat the counter expand tests */
      46             : #define EXPAND_TEST_ROUNDS 3
      47             : 
      48             : /*
      49             :  * Let a simple counter vector grow and verify that
      50             :  * the stats epoch is increased only when the vector
      51             :  * is expanded.
      52             :  */
      53             : static clib_error_t *
      54           1 : test_simple_counter_expand (vlib_main_t *vm)
      55             : {
      56           1 :   vlib_simple_counter_main_t counter = {
      57             :     .name = "test-simple-counter-expand",
      58             :     .stat_segment_name = "/vlib/test-simple-counter-expand",
      59             :   };
      60             :   int i, index;
      61             :   uint64_t epoch, new_epoch;
      62             : 
      63             :   // Create one counter to allocate the vector.
      64           1 :   vlib_validate_simple_counter (&counter, 0);
      65           1 :   epoch = get_stats_epoch ();
      66             : 
      67           4 :   for (i = 0; i < EXPAND_TEST_ROUNDS; i++)
      68             :     {
      69             :       // Check how many elements fit into the counter vector without expanding
      70             :       // that. The next validate calls should not increase the stats segment
      71             :       // epoch.
      72           3 :       int mem_size = vec_max_len (counter.counters[0]);
      73          20 :       for (index = 1; index <= mem_size - 1; index++)
      74             :         {
      75          17 :           vlib_validate_simple_counter (&counter, index);
      76          17 :           new_epoch = get_stats_epoch ();
      77          17 :           if (new_epoch != epoch)
      78           0 :             return clib_error_return (
      79             :               0, "Stats segment epoch should not increase");
      80             :         }
      81             : 
      82             :       // The next counter index does not fit and it will extend the vector.
      83             :       // The stats segment epoch should increase.
      84           3 :       vlib_validate_simple_counter (&counter, index + 1);
      85           3 :       new_epoch = get_stats_epoch ();
      86           3 :       if (new_epoch == epoch)
      87           0 :         return clib_error_return (0,
      88             :                                   "Stats segment epoch should have increased");
      89           3 :       epoch = new_epoch;
      90             :     }
      91             : 
      92           1 :   vlib_free_simple_counter (&counter);
      93           1 :   vlib_validate_simple_counter (&counter, 0);
      94             : 
      95           1 :   return 0;
      96             : }
      97             : 
      98             : /*
      99             :  * Let a combined counter vector grow and verify that
     100             :  * the stats epoch is increased only when the vector
     101             :  * is expanded.
     102             :  */
     103             : static clib_error_t *
     104           1 : test_combined_counter_expand (vlib_main_t *vm)
     105             : {
     106           1 :   vlib_combined_counter_main_t counter = {
     107             :     .name = "test-combined-counter-expand",
     108             :     .stat_segment_name = "/vlib/test-combined-counter-expand",
     109             :   };
     110             :   int i, index;
     111             :   uint64_t epoch, new_epoch;
     112             : 
     113             :   // Create one counter to allocate the vector.
     114           1 :   vlib_validate_combined_counter (&counter, 0);
     115           1 :   epoch = get_stats_epoch ();
     116             : 
     117           4 :   for (i = 0; i < EXPAND_TEST_ROUNDS; i++)
     118             :     {
     119             :       // Check how many elements fit into the counter vector without expanding
     120             :       // that. The next validate calls should not increase the stats segment
     121             :       // epoch.
     122           3 :       int mem_size = vec_max_len (counter.counters[0]);
     123          17 :       for (index = 1; index <= mem_size - 1; index++)
     124             :         {
     125          14 :           vlib_validate_combined_counter (&counter, index);
     126          14 :           new_epoch = get_stats_epoch ();
     127          14 :           if (new_epoch != epoch)
     128           0 :             return clib_error_return (
     129             :               0, "Stats segment epoch should not increase");
     130             :         }
     131             : 
     132             :       // The next counter index does not fit and it will extend the vector.
     133             :       // The stats segment epoch should increase.
     134           3 :       vlib_validate_combined_counter (&counter, index + 1);
     135           3 :       new_epoch = get_stats_epoch ();
     136           3 :       if (new_epoch == epoch)
     137           0 :         return clib_error_return (0,
     138             :                                   "Stats segment epoch should have increased");
     139           3 :       epoch = new_epoch;
     140             :     }
     141             : 
     142           1 :   vlib_free_combined_counter (&counter);
     143           1 :   vlib_validate_combined_counter (&counter, 0);
     144             : 
     145           1 :   return 0;
     146             : }
     147             : 
     148             : static clib_error_t *
     149           1 : test_simple_counter (vlib_main_t *vm, int test_case)
     150             : {
     151             :   clib_error_t *error;
     152             : 
     153           1 :   switch (test_case)
     154             :     {
     155           1 :     case test_expand:
     156           1 :       error = test_simple_counter_expand (vm);
     157           1 :       break;
     158             : 
     159           0 :     default:
     160           0 :       return clib_error_return (0, "no such test");
     161             :     }
     162             : 
     163           1 :   return error;
     164             : }
     165             : 
     166             : static clib_error_t *
     167           1 : test_combined_counter (vlib_main_t *vm, int test_case)
     168             : {
     169             :   clib_error_t *error;
     170             : 
     171           1 :   switch (test_case)
     172             :     {
     173           1 :     case test_expand:
     174           1 :       error = test_combined_counter_expand (vm);
     175           1 :       break;
     176             : 
     177           0 :     default:
     178           0 :       return clib_error_return (0, "no such test");
     179             :     }
     180             : 
     181           1 :   return error;
     182             : }
     183             : 
     184             : static clib_error_t *
     185           2 : test_counter_command_fn (vlib_main_t *vm, unformat_input_t *input,
     186             :                          vlib_cli_command_t *cmd)
     187             : {
     188             :   clib_error_t *error;
     189           2 :   int counter_type = -1;
     190           2 :   int test_case = -1;
     191             : 
     192           6 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     193             :     {
     194           4 :       if (unformat (input, "simple"))
     195           1 :         counter_type = type_simple;
     196           3 :       else if (unformat (input, "combined"))
     197           1 :         counter_type = type_combined;
     198           2 :       else if (unformat (input, "expand"))
     199           2 :         test_case = test_expand;
     200             :       else
     201           0 :         return clib_error_return (0, "unknown input '%U'",
     202             :                                   format_unformat_error, input);
     203             :     }
     204             : 
     205           2 :   if (test_case == -1)
     206           0 :     return clib_error_return (0, "no such test");
     207             : 
     208           2 :   switch (counter_type)
     209             :     {
     210           1 :     case type_simple:
     211           1 :       error = test_simple_counter (vm, test_case);
     212           1 :       break;
     213             : 
     214           1 :     case type_combined:
     215           1 :       error = test_combined_counter (vm, test_case);
     216           1 :       break;
     217             : 
     218           0 :     default:
     219           0 :       return clib_error_return (0, "no such test");
     220             :     }
     221             : 
     222           2 :   return error;
     223             : }
     224             : 
     225       16239 : VLIB_CLI_COMMAND (test_counter_command, static) = {
     226             :   .path = "test counter",
     227             :   .short_help = "test counter [simple | combined] expand",
     228             :   .function = test_counter_command_fn,
     229             : };
     230             : 
     231             : static clib_error_t *
     232         559 : test_counter_init (vlib_main_t *vm)
     233             : {
     234         559 :   return (0);
     235             : }
     236             : 
     237        6159 : VLIB_INIT_FUNCTION (test_counter_init);
     238             : 
     239             : /*
     240             :  * fd.io coding-style-patch-verification: ON
     241             :  *
     242             :  * Local Variables:
     243             :  * eval: (c-set-style "gnu")
     244             :  * End:
     245             :  */

Generated by: LCOV version 1.14