crypto crypto-openssl: support hashing operations
[vpp.git] / src / plugins / unittest / counter_test.c
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 <vpp/stats/stat_segment.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 get_stats_epoch ()
40 {
41   stat_segment_main_t *sm = &stat_segment_main;
42   return sm->shared_header->epoch;
43 }
44
45 /*
46  * Return the maximum element count of the vector based on its allocated
47  * memory.
48  */
49 static int
50 get_vec_mem_size (void *v, uword data_size)
51 {
52   stat_segment_main_t *sm = &stat_segment_main;
53
54   if (v == 0)
55     return 0;
56
57   uword aligned_header_bytes = vec_header_bytes (0);
58   void *p = v - aligned_header_bytes;
59   void *oldheap = clib_mem_set_heap (sm->heap);
60   int mem_size = (clib_mem_size (p) - aligned_header_bytes) / data_size;
61   clib_mem_set_heap (oldheap);
62
63   return mem_size;
64 }
65
66 /* number of times to repeat the counter expand tests */
67 #define EXPAND_TEST_ROUNDS 3
68
69 /*
70  * Let a simple counter vector grow and verify that
71  * the stats epoch is increased only when the vector
72  * is expanded.
73  */
74 static clib_error_t *
75 test_simple_counter_expand (vlib_main_t *vm)
76 {
77   vlib_simple_counter_main_t counter = {
78     .name = "test-simple-counter-expand",
79     .stat_segment_name = "/vlib/test-simple-counter-expand",
80   };
81   int i, index;
82   uint64_t epoch, new_epoch;
83
84   // Create one counter to allocate the vector.
85   vlib_validate_simple_counter (&counter, 0);
86   epoch = get_stats_epoch ();
87
88   for (i = 0; i < EXPAND_TEST_ROUNDS; i++)
89     {
90       // Check how many elements fit into the counter vector without expanding
91       // that. The next validate calls should not increase the stats segment
92       // epoch.
93       int mem_size = get_vec_mem_size (counter.counters[0],
94                                        sizeof ((counter.counters[0])[0]));
95       for (index = 1; index <= mem_size - 1; index++)
96         {
97           vlib_validate_simple_counter (&counter, index);
98           new_epoch = get_stats_epoch ();
99           if (new_epoch != epoch)
100             return clib_error_return (
101               0, "Stats segment epoch should not increase");
102         }
103
104       // The next counter index does not fit and it will extend the vector.
105       // The stats segment epoch should increase.
106       vlib_validate_simple_counter (&counter, index + 1);
107       new_epoch = get_stats_epoch ();
108       if (new_epoch == epoch)
109         return clib_error_return (0,
110                                   "Stats segment epoch should have increased");
111       epoch = new_epoch;
112     }
113
114   return 0;
115 }
116
117 /*
118  * Let a combined counter vector grow and verify that
119  * the stats epoch is increased only when the vector
120  * is expanded.
121  */
122 static clib_error_t *
123 test_combined_counter_expand (vlib_main_t *vm)
124 {
125   vlib_combined_counter_main_t counter = {
126     .name = "test-combined-counter-expand",
127     .stat_segment_name = "/vlib/test-combined-counter-expand",
128   };
129   int i, index;
130   uint64_t epoch, new_epoch;
131
132   // Create one counter to allocate the vector.
133   vlib_validate_combined_counter (&counter, 0);
134   epoch = get_stats_epoch ();
135
136   for (i = 0; i < EXPAND_TEST_ROUNDS; i++)
137     {
138       // Check how many elements fit into the counter vector without expanding
139       // that. The next validate calls should not increase the stats segment
140       // epoch.
141       int mem_size = get_vec_mem_size (counter.counters[0],
142                                        sizeof ((counter.counters[0])[0]));
143       for (index = 1; index <= mem_size - 1; index++)
144         {
145           vlib_validate_combined_counter (&counter, index);
146           new_epoch = get_stats_epoch ();
147           if (new_epoch != epoch)
148             return clib_error_return (
149               0, "Stats segment epoch should not increase");
150         }
151
152       // The next counter index does not fit and it will extend the vector.
153       // The stats segment epoch should increase.
154       vlib_validate_combined_counter (&counter, index + 1);
155       new_epoch = get_stats_epoch ();
156       if (new_epoch == epoch)
157         return clib_error_return (0,
158                                   "Stats segment epoch should have increased");
159       epoch = new_epoch;
160     }
161
162   return 0;
163 }
164
165 static clib_error_t *
166 test_simple_counter (vlib_main_t *vm, int test_case)
167 {
168   clib_error_t *error;
169
170   switch (test_case)
171     {
172     case test_expand:
173       error = test_simple_counter_expand (vm);
174       break;
175
176     default:
177       return clib_error_return (0, "no such test");
178     }
179
180   return error;
181 }
182
183 static clib_error_t *
184 test_combined_counter (vlib_main_t *vm, int test_case)
185 {
186   clib_error_t *error;
187
188   switch (test_case)
189     {
190     case test_expand:
191       error = test_combined_counter_expand (vm);
192       break;
193
194     default:
195       return clib_error_return (0, "no such test");
196     }
197
198   return error;
199 }
200
201 static clib_error_t *
202 test_counter_command_fn (vlib_main_t *vm, unformat_input_t *input,
203                          vlib_cli_command_t *cmd)
204 {
205   clib_error_t *error;
206   int counter_type = -1;
207   int test_case = -1;
208
209   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
210     {
211       if (unformat (input, "simple"))
212         counter_type = type_simple;
213       else if (unformat (input, "combined"))
214         counter_type = type_combined;
215       else if (unformat (input, "expand"))
216         test_case = test_expand;
217       else
218         return clib_error_return (0, "unknown input '%U'",
219                                   format_unformat_error, input);
220     }
221
222   if (test_case == -1)
223     return clib_error_return (0, "no such test");
224
225   switch (counter_type)
226     {
227     case type_simple:
228       error = test_simple_counter (vm, test_case);
229       break;
230
231     case type_combined:
232       error = test_combined_counter (vm, test_case);
233       break;
234
235     default:
236       return clib_error_return (0, "no such test");
237     }
238
239   return error;
240 }
241
242 VLIB_CLI_COMMAND (test_counter_command, static) = {
243   .path = "test counter",
244   .short_help = "test counter [simple | combined] expand",
245   .function = test_counter_command_fn,
246 };
247
248 static clib_error_t *
249 test_counter_init (vlib_main_t *vm)
250 {
251   return (0);
252 }
253
254 VLIB_INIT_FUNCTION (test_counter_init);
255
256 /*
257  * fd.io coding-style-patch-verification: ON
258  *
259  * Local Variables:
260  * eval: (c-set-style "gnu")
261  * End:
262  */