Initial commit of vpp code.
[vpp.git] / vppinfra / vppinfra / test_serialize.c
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16   Copyright (c) 2005 Eliot Dresselhaus
17
18   Permission is hereby granted, free of charge, to any person obtaining
19   a copy of this software and associated documentation files (the
20   "Software"), to deal in the Software without restriction, including
21   without limitation the rights to use, copy, modify, merge, publish,
22   distribute, sublicense, and/or sell copies of the Software, and to
23   permit persons to whom the Software is furnished to do so, subject to
24   the following conditions:
25
26   The above copyright notice and this permission notice shall be
27   included in all copies or substantial portions of the Software.
28
29   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 */
37
38 #include <vppinfra/format.h>
39 #include <vppinfra/random.h>
40 #include <vppinfra/serialize.h>
41 #include <vppinfra/os.h>
42
43 #define foreach_my_vector_type                  \
44   _ (u8, a8)                                    \
45   _ (u16, a16)                                  \
46   _ (u32, a32)
47
48 typedef struct {
49 #define _(t,f) t f;
50   foreach_my_vector_type
51 #undef _
52 } my_vector_type_t;
53
54 static void serialize_my_vector_type_single (serialize_main_t * m, va_list * va)
55 {
56   my_vector_type_t * v = va_arg (*va, my_vector_type_t *);
57   u32 n = va_arg (*va, u32);
58   u32 i;
59
60   for (i = 0; i < n; i++)
61     {
62 #define _(t,f) serialize_integer (m, v[i].f, sizeof (v[i].f));
63       foreach_my_vector_type;
64     }
65 #undef _
66 }
67
68 static void unserialize_my_vector_type_single (serialize_main_t * m, va_list * va)
69 {
70   my_vector_type_t * v = va_arg (*va, my_vector_type_t *);
71   u32 n = va_arg (*va, u32);
72   u32 i;
73
74   for (i = 0; i < n; i++)
75     {
76 #define _(t,f) { u32 tmp; unserialize_integer (m, &tmp, sizeof (v[i].f)); v[i].f = tmp; }
77       foreach_my_vector_type;
78 #undef _
79     }
80 }
81
82 static void serialize_my_vector_type_multiple (serialize_main_t * m, va_list * va)
83 {
84   my_vector_type_t * v = va_arg (*va, my_vector_type_t *);
85   u32 n = va_arg (*va, u32);
86
87 #define _(t,f)                                  \
88   serialize_multiple                            \
89     (m,                                         \
90      &v[0].f,                                   \
91      STRUCT_SIZE_OF (my_vector_type_t, f),      \
92      STRUCT_STRIDE_OF (my_vector_type_t, f),    \
93      n);
94
95   foreach_my_vector_type;
96
97 #undef _
98 }
99
100 static void unserialize_my_vector_type_multiple (serialize_main_t * m, va_list * va)
101 {
102   my_vector_type_t * v = va_arg (*va, my_vector_type_t *);
103   u32 n = va_arg (*va, u32);
104
105 #define _(t,f)                                  \
106   unserialize_multiple                          \
107     (m,                                         \
108      &v[0].f,                                   \
109      STRUCT_SIZE_OF (my_vector_type_t, f),      \
110      STRUCT_STRIDE_OF (my_vector_type_t, f),    \
111      n);
112
113   foreach_my_vector_type;
114
115 #undef _
116 }
117
118 typedef struct {
119   u32 n_iter;
120   u32 seed;
121   u32 verbose;
122   u32 multiple;
123   u32 max_len;
124
125   my_vector_type_t ** test_vectors;
126
127   char * dump_file;
128
129   serialize_main_t serialize_main;
130   serialize_main_t unserialize_main;
131 } test_serialize_main_t;
132
133 int test_serialize_main (unformat_input_t * input)
134 {
135   clib_error_t * error = 0;
136   test_serialize_main_t _tm, * tm = &_tm;
137   serialize_main_t * sm = &tm->serialize_main;
138   serialize_main_t * um = &tm->unserialize_main;
139   uword i;
140
141   memset (tm, 0, sizeof (tm[0]));
142   tm->n_iter = 100;
143   tm->seed = 1;
144   tm->max_len = 128;
145   tm->verbose = 0;
146   tm->multiple = 1;
147
148   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
149     {
150       if (unformat (input, "iter %d", &tm->n_iter))
151         ;
152       else if (unformat (input, "seed %d", &tm->seed))
153         ;
154       else if (unformat (input, "file %s", &tm->dump_file))
155         ;
156       else if (unformat (input, "max-len %d", &tm->max_len))
157         ;
158       else if (unformat (input, "multiple %=", &tm->multiple, 1))
159         ;
160       else if (unformat (input, "single %=", &tm->multiple, 0))
161         ;
162       else if (unformat (input, "verbose %=", &tm->verbose, 1))
163         ;
164       else
165         {
166           error = clib_error_create ("unknown input `%U'\n",
167                                      format_unformat_error, input);
168           goto done;
169         }
170     }
171
172   if (tm->seed == 0)
173     tm->seed = random_default_seed ();
174
175   clib_warning ("iter %d seed %d max-len %d", tm->n_iter, tm->seed, tm->max_len);
176
177 #ifdef CLIB_UNIX
178   if (tm->dump_file)
179     serialize_open_unix_file (sm, tm->dump_file);
180   else
181 #endif
182     serialize_open_vector (sm, 0);
183
184   vec_resize (tm->test_vectors, tm->n_iter);
185   for (i = 0; i < tm->n_iter; i++)
186     {
187       uword l = 1 + (random_u32 (&tm->seed) % tm->max_len);
188       my_vector_type_t * mv;
189
190       vec_resize (tm->test_vectors[i], l);
191       vec_foreach (mv, tm->test_vectors[i])
192         {
193 #define _(t,f) mv->f = random_u32 (&tm->seed) & pow2_mask (31);
194           foreach_my_vector_type;
195 #undef _
196         }
197
198       vec_serialize (sm, tm->test_vectors[i],
199                      tm->multiple ? serialize_my_vector_type_multiple : serialize_my_vector_type_single);
200     }
201
202   if (tm->verbose)
203     clib_warning ("overflow vector max bytes %d", vec_max_len (sm->stream.overflow_buffer));
204
205   serialize_close (sm);
206
207 #ifdef CLIB_UNIX
208   if (tm->dump_file)
209     {
210       if ((error = unserialize_open_unix_file (um, tm->dump_file)))
211         goto done;
212     }
213   else
214 #endif
215     {
216       u8 * v = serialize_close_vector (sm);
217       unserialize_open_data (um, v, vec_len (v));
218     }
219
220   for (i = 0; i < tm->n_iter; i++)
221     {
222       my_vector_type_t * mv0;
223       my_vector_type_t * mv1;
224
225       vec_unserialize (um, &mv0,
226                        tm->multiple ? unserialize_my_vector_type_multiple  : unserialize_my_vector_type_single);
227       mv1 = tm->test_vectors[i];
228
229       if (vec_len (mv0) != vec_len (mv1))
230         os_panic ();
231       if (memcmp (mv0, mv1, vec_len (mv0) * sizeof (mv0[0])))
232         os_panic ();
233
234       vec_free (mv0);
235     }
236
237  done:
238   if (error)
239     clib_error_report (error);
240   return 0;
241 }
242
243 #ifdef CLIB_UNIX
244 int main (int argc, char * argv [])
245 {
246   unformat_input_t i;
247   int r;
248
249   unformat_init_command_line (&i, argv);
250   r = test_serialize_main (&i);
251   unformat_free (&i);
252   return r;
253 }
254 #endif