Merge branch 'milestone/monitoring' into jennifer/request_id
[trust_router.git] / trp / test / rtbl_test.c
1 /*
2  * Copyright (c) 2016, JANET(UK)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * 3. Neither the name of JANET(UK) nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31  * OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34
35 #include <stdio.h>
36 #include <talloc.h>
37 #include <string.h>
38 #include <assert.h>
39
40 #include <tr_name_internal.h>
41 #include <trp_route.h>
42 #include <trp_internal.h>
43 #include <trp_rtable.h>
44
45 char *apc[]={"apc1", "apc2", "apc3"};
46 size_t n_apc=sizeof(apc)/sizeof(apc[0]);
47 char *realm[]={"realm1", "realm2", "realm3"};
48 size_t n_realm=sizeof(realm)/sizeof(realm[0]);
49 char *peer[]={"peer1", "peer2", "peer3"};
50 size_t n_peer=sizeof(peer)/sizeof(peer[0]);
51
52 static unsigned int metric1(size_t a, size_t b, size_t c)
53 {
54   return a+b+c;
55 }
56
57 static unsigned int metric2(size_t a, size_t b, size_t c)
58 {
59   return a+b+c+25;
60 }
61
62 static unsigned int metric3(size_t a, size_t b, size_t c)
63 {
64   return a*(b+c)+b*c;
65 }
66
67 static void populate_rtable(TRP_RTABLE *table, unsigned int (*metric)(size_t, size_t, size_t))
68 {
69   TRP_ROUTE *entry=NULL;
70   size_t ii=0, jj=0, kk=0;
71   struct timespec ts={0,0};
72
73   for (ii=0; ii<n_apc; ii++) {
74     for (jj=0; jj<n_realm; jj++) {
75       for (kk=0; kk<n_peer; kk++) {
76         entry=trp_route_new(NULL);
77         trp_route_set_comm(entry, tr_new_name(apc[ii]));
78         trp_route_set_realm(entry, tr_new_name(realm[jj]));
79         trp_route_set_trust_router(entry, tr_new_name(realm[jj]));
80         trp_route_set_peer(entry, tr_new_name(peer[kk]));
81         trp_route_set_metric(entry, metric(ii,jj,kk));
82         trp_route_set_next_hop(entry, tr_new_name(peer[kk]));
83         ts=(struct timespec){jj+1,ii+kk+1};
84         trp_route_set_expiry(entry, &ts);
85         trp_rtable_add(table, entry);
86         entry=NULL; /* entry belongs to the table now */
87       }
88     }
89   }
90 }
91
92 static void verify_rtable(TRP_RTABLE *table, unsigned int (*metric)(size_t, size_t, size_t))
93 {
94   TRP_ROUTE *entry=NULL;
95   size_t ii=0, jj=0, kk=0;
96   size_t len=0;
97   TR_NAME *apc_n, *realm_n, *peer_n;
98
99   for (ii=0; ii<n_apc; ii++) {
100     for (jj=0; jj<n_realm; jj++) {
101       for (kk=0; kk<n_peer; kk++) {
102         apc_n=tr_new_name(apc[ii]);
103         realm_n=tr_new_name(realm[jj]);
104         peer_n=tr_new_name(peer[kk]);
105         entry=trp_rtable_get_entry(table, apc_n, realm_n, peer_n);
106         tr_free_name(apc_n);
107         tr_free_name(realm_n);
108         tr_free_name(peer_n);
109
110         assert(entry!=NULL);
111
112         len=trp_route_get_comm(entry)->len;
113         assert(len==strlen(apc[ii]));
114         assert(0==strncmp(trp_route_get_comm(entry)->buf, apc[ii], len));
115
116         len=trp_route_get_realm(entry)->len;
117         assert(len==strlen(realm[jj]));
118         assert(0==strncmp(trp_route_get_realm(entry)->buf, realm[jj], len));
119         
120         len=trp_route_get_peer(entry)->len;
121         assert(len==strlen(peer[kk]));
122         assert(0==strncmp(trp_route_get_peer(entry)->buf, peer[kk], len));
123         
124         len=trp_route_get_trust_router(entry)->len;
125         assert(len==strlen(realm[jj]));
126         assert(0==strncmp(trp_route_get_trust_router(entry)->buf, realm[jj], len));
127
128         assert(trp_route_get_metric(entry)==metric(ii,jj,kk));
129
130         len=trp_route_get_next_hop(entry)->len;
131         assert(len==strlen(peer[kk]));
132         assert(0==strncmp(trp_route_get_next_hop(entry)->buf, peer[kk], len));
133
134         assert(trp_route_is_selected(entry)==0);
135         assert(trp_route_get_expiry(entry)->tv_sec==jj+1);
136         assert(trp_route_get_expiry(entry)->tv_nsec==ii+kk+1);
137
138         printf("{%s %s %s} entry OK!\n", apc[ii], realm[jj], peer[kk]);
139       }
140     }
141   }
142 }
143
144 static int is_in(char *a, char *b[], size_t n_b)
145 {
146   size_t count=0;
147
148   while (n_b--) {
149     if (0==strcmp(a, b[n_b]))
150       count++;
151   }
152   return count;
153 }
154 static void verify_apc_list(TRP_RTABLE *table)
155 {
156   size_t n=0;
157   TR_NAME **apcs_found=trp_rtable_get_comms(table, &n);
158   assert(n==n_apc);
159   while(n--)
160     assert(1==is_in(apcs_found[n]->buf, apc, n_apc));
161 }
162
163 static void verify_apc_realm_lists(TRP_RTABLE *table)
164 {
165   size_t n=0, ii=0;
166   TR_NAME *apc_n=NULL, **realms_found=NULL;
167
168   for (ii=0; ii<n_apc; ii++) {
169     apc_n=tr_new_name(apc[ii]);
170     realms_found=trp_rtable_get_comm_realms(table, apc_n, &n);
171     tr_free_name(apc_n);
172     assert(n==n_realm);
173     while (n--)
174       assert(1==is_in(realms_found[n]->buf, realm, n_realm));
175     talloc_free(realms_found);
176     printf("APC %s ok!\n", apc[ii]);
177   }
178 }
179
180 static void verify_get_apc_entries(TRP_RTABLE *table)
181 {
182   size_t n=0, ii=0;
183   TRP_ROUTE **apc_entries=NULL;
184   TR_NAME *apc_n=NULL;
185
186   for (ii=0; ii<n_apc; ii++) {
187     apc_n=tr_new_name(apc[ii]);
188     apc_entries=trp_rtable_get_comm_entries(table, apc_n, &n);
189     tr_free_name(apc_n);
190     assert(n==n_realm*n_peer);
191     while (n--) {
192       assert(0==strncmp(trp_route_get_comm(apc_entries[n])->buf,
193                         apc[ii],
194                         trp_route_get_comm(apc_entries[n])->len));
195       assert(1==is_in(trp_route_get_realm(apc_entries[n])->buf, realm, n_realm));
196       assert(1==is_in(trp_route_get_peer(apc_entries[n])->buf, peer, n_peer));
197     }
198     printf("APC %s ok!\n", apc[ii]);
199     talloc_free(apc_entries);
200   }
201 }
202
203 static void verify_get_realm_entries(TRP_RTABLE *table)
204 {
205   size_t n=0, ii=0, jj=0;
206   TRP_ROUTE **realm_entries=NULL;
207   TR_NAME *apc_n=NULL, *realm_n=NULL;
208
209   for (ii=0; ii<n_apc; ii++) {
210     for (jj=0; jj<n_realm; jj++) {
211       apc_n=tr_new_name(apc[ii]);
212       realm_n=tr_new_name(realm[jj]);
213       realm_entries=trp_rtable_get_realm_entries(table, apc_n, realm_n, &n);
214       tr_free_name(apc_n);
215       tr_free_name(realm_n);
216       assert(n==n_peer);
217       while (n--) {
218         assert(0==strncmp(trp_route_get_comm(realm_entries[n])->buf,
219                           apc[ii],
220                           trp_route_get_comm(realm_entries[n])->len));
221         assert(0==strncmp(trp_route_get_realm(realm_entries[n])->buf,
222                           realm[jj],
223                           trp_route_get_realm(realm_entries[n])->len));
224         assert(1==is_in(trp_route_get_peer(realm_entries[n])->buf, peer, n_peer));
225       }
226       printf("APC %s realm %s ok!\n", apc[ii], realm[jj]);
227       talloc_free(realm_entries);
228     }
229   }
230 }
231
232 /* doesn't work if c not in a */
233 static size_t get_index(char *c, char **a, size_t n_a)
234 {
235   while(n_a--) {
236     if (0==strcmp(c, a[n_a]))
237       return n_a;
238   }
239   return 0;
240 }
241
242 static void update_metric(TRP_RTABLE *table, unsigned int (*new_metric)(size_t, size_t, size_t))
243 {
244   TRP_ROUTE **entries=NULL;
245   size_t n=0, ii=0,jj=0,kk=0;
246
247   entries= trp_rtable_get_entries(NULL, table, &n);
248   while (n--) {
249     ii=get_index(trp_route_get_comm(entries[n])->buf, apc, n_apc);
250     jj=get_index(trp_route_get_realm(entries[n])->buf, realm, n_realm);
251     kk=get_index(trp_route_get_peer(entries[n])->buf, peer, n_peer);
252     trp_route_set_metric(entries[n],
253                           new_metric(ii,jj,kk));
254   }
255   talloc_free(entries);
256 }
257
258 static void remove_entries(TRP_RTABLE *table)
259 {
260   size_t n=trp_rtable_size(table);
261   size_t ii,jj,kk;
262   TR_NAME *apc_n, *realm_n, *peer_n;
263   TRP_ROUTE *entry=NULL;
264
265   for (ii=0; ii<n_apc; ii++) {
266     for (jj=0; jj<n_realm; jj++) {
267       for (kk=0; kk<n_realm; kk++) {
268         apc_n=tr_new_name(apc[ii]);
269         realm_n=tr_new_name(realm[jj]);
270         peer_n=tr_new_name(peer[kk]);
271         entry=trp_rtable_get_entry(table, apc_n, realm_n, peer_n);
272         assert(entry !=NULL);
273         tr_free_name(apc_n);
274         tr_free_name(realm_n);
275         tr_free_name(peer_n);
276         trp_rtable_remove(table, entry);
277         entry=NULL;
278         assert(trp_rtable_size(table)==--n);
279       }
280     }
281   }
282 }
283
284
285 static void print_rtable(TRP_RTABLE *table)
286 {
287   char *s=trp_rtable_to_str(NULL, table, NULL, NULL);
288   printf("%s",s);
289   talloc_free(s);
290 }
291
292 int main(void)
293 {
294   TRP_RTABLE *table=NULL;
295   table=trp_rtable_new();
296   populate_rtable(table, metric1);
297   print_rtable(table);
298
299   printf("\nVerifying routing table...\n");
300   verify_rtable(table, metric1);
301   printf("                         ...success!\n");
302
303   printf("\nVerifying APC list...\n");
304   verify_apc_list(table);
305   printf("                    ...success!\n");
306
307   printf("\nVerifying APC realm lists...\n");
308   verify_apc_realm_lists(table);
309   printf("                    ...success!\n");
310
311   printf("\nVerifying APC entry lists...\n");
312   verify_get_apc_entries(table);
313   printf("                           ...success!\n");
314
315   printf("\nVerifying realm entry lists...\n");
316   verify_get_realm_entries(table);
317   printf("                              ...success!\n");
318
319   printf("\nVerifying table value update...\n");
320   update_metric(table, metric2); /* changes the metric value in each element in-place */
321   verify_rtable(table, metric2);
322   printf("                              ...success!\n");
323
324   printf("\nVerifying element replacement...\n");
325   populate_rtable(table, metric3); /* replaces all the elements with new ones */
326   verify_rtable(table, metric3);
327   printf("                               ...success!\n");
328
329   printf("\nVerifying element removal...\n");
330   remove_entries(table);
331   print_rtable(table);
332   printf("                           ...success!\n");
333
334   printf("\nRepopulating table...\n");
335   populate_rtable(table, metric3);
336   verify_rtable(table, metric3);
337   printf("                               ...success!\n");
338
339   trp_rtable_free(table);
340   return 0;
341 }