Update the routing table when TRP updates are received.
[trust_router.git] / trp / test / rtbl_test.c
1 #include <stdio.h>
2 #include <talloc.h>
3 #include <string.h>
4 #include <assert.h>
5
6 #include <trust_router/tr_name.h>
7 #include <trp_internal.h>
8 #include <trp_rtable.h>
9
10 char *apc[]={"apc1", "apc2", "apc3"};
11 size_t n_apc=sizeof(apc)/sizeof(apc[0]);
12 char *realm[]={"realm1", "realm2", "realm3"};
13 size_t n_realm=sizeof(realm)/sizeof(realm[0]);
14 char *peer[]={"peer1", "peer2", "peer3"};
15 size_t n_peer=sizeof(peer)/sizeof(peer[0]);
16
17 static unsigned int metric1(size_t a, size_t b, size_t c)
18 {
19   return a+b+c;
20 }
21
22 static unsigned int metric2(size_t a, size_t b, size_t c)
23 {
24   return a+b+c+25;
25 }
26
27 static unsigned int metric3(size_t a, size_t b, size_t c)
28 {
29   return a*(b+c)+b*c;
30 }
31
32 static void populate_rtable(TRP_RTABLE *table, unsigned int (*metric)(size_t, size_t, size_t))
33 {
34   TRP_RENTRY *entry=NULL;
35   size_t ii=0, jj=0, kk=0;
36   struct timespec ts={0,0};
37
38   for (ii=0; ii<n_apc; ii++) {
39     for (jj=0; jj<n_realm; jj++) {
40       for (kk=0; kk<n_peer; kk++) {
41         entry=trp_rentry_new(NULL);
42         trp_rentry_set_apc(entry, tr_new_name(apc[ii]));
43         trp_rentry_set_realm(entry, tr_new_name(realm[jj]));
44         trp_rentry_set_trust_router(entry, tr_new_name(realm[jj]));
45         trp_rentry_set_peer(entry, tr_new_name(peer[kk]));
46         trp_rentry_set_metric(entry, metric(ii,jj,kk));
47         trp_rentry_set_next_hop(entry, tr_new_name(peer[kk]));
48         ts=(struct timespec){jj+1,ii+kk+1};
49         trp_rentry_set_expiry(entry, &ts);
50         trp_rtable_add(table, entry);
51         entry=NULL; /* entry belongs to the table now */
52       }
53     }
54   }
55 }
56
57 static void verify_rtable(TRP_RTABLE *table, unsigned int (*metric)(size_t, size_t, size_t))
58 {
59   TRP_RENTRY *entry=NULL;
60   size_t ii=0, jj=0, kk=0;
61   size_t len=0;
62   TR_NAME *apc_n, *realm_n, *peer_n;
63
64   for (ii=0; ii<n_apc; ii++) {
65     for (jj=0; jj<n_realm; jj++) {
66       for (kk=0; kk<n_peer; kk++) {
67         apc_n=tr_new_name(apc[ii]);
68         realm_n=tr_new_name(realm[jj]);
69         peer_n=tr_new_name(peer[kk]);
70         entry=trp_rtable_get_entry(table, apc_n, realm_n, peer_n);
71         tr_free_name(apc_n);
72         tr_free_name(realm_n);
73         tr_free_name(peer_n);
74
75         assert(entry!=NULL);
76
77         len=trp_rentry_get_apc(entry)->len;
78         assert(len==strlen(apc[ii]));
79         assert(0==strncmp(trp_rentry_get_apc(entry)->buf, apc[ii], len));
80
81         len=trp_rentry_get_realm(entry)->len;
82         assert(len==strlen(realm[jj]));
83         assert(0==strncmp(trp_rentry_get_realm(entry)->buf, realm[jj], len));
84         
85         len=trp_rentry_get_peer(entry)->len;
86         assert(len==strlen(peer[kk]));
87         assert(0==strncmp(trp_rentry_get_peer(entry)->buf, peer[kk], len));
88         
89         len=trp_rentry_get_trust_router(entry)->len;
90         assert(len==strlen(realm[jj]));
91         assert(0==strncmp(trp_rentry_get_trust_router(entry)->buf, realm[jj], len));
92
93         assert(trp_rentry_get_metric(entry)==metric(ii,jj,kk));
94
95         len=trp_rentry_get_next_hop(entry)->len;
96         assert(len==strlen(peer[kk]));
97         assert(0==strncmp(trp_rentry_get_next_hop(entry)->buf, peer[kk], len));
98
99         assert(trp_rentry_get_selected(entry)==0);
100         assert(trp_rentry_get_expiry(entry)->tv_sec==jj+1);
101         assert(trp_rentry_get_expiry(entry)->tv_nsec==ii+kk+1);
102
103         printf("{%s %s %s} entry OK!\n", apc[ii], realm[jj], peer[kk]);
104       }
105     }
106   }
107 }
108
109 static int is_in(char *a, char *b[], size_t n_b)
110 {
111   size_t count=0;
112
113   while (n_b--) {
114     if (0==strcmp(a, b[n_b]))
115       count++;
116   }
117   return count;
118 }
119 static void verify_apc_list(TRP_RTABLE *table)
120 {
121   size_t n=0;
122   TR_NAME **apcs_found=trp_rtable_get_apcs(table, &n);
123   assert(n==n_apc);
124   while(n--)
125     assert(1==is_in(apcs_found[n]->buf, apc, n_apc));
126 }
127
128 static void verify_apc_realm_lists(TRP_RTABLE *table)
129 {
130   size_t n=0, ii=0;
131   TR_NAME *apc_n=NULL, **realms_found=NULL;
132
133   for (ii=0; ii<n_apc; ii++) {
134     apc_n=tr_new_name(apc[ii]);
135     realms_found=trp_rtable_get_apc_realms(table, apc_n, &n);
136     tr_free_name(apc_n);
137     assert(n==n_realm);
138     while (n--)
139       assert(1==is_in(realms_found[n]->buf, realm, n_realm));
140     talloc_free(realms_found);
141     printf("APC %s ok!\n", apc[ii]);
142   }
143 }
144
145 static void verify_get_apc_entries(TRP_RTABLE *table)
146 {
147   size_t n=0, ii=0;
148   TRP_RENTRY **apc_entries=NULL;
149   TR_NAME *apc_n=NULL;
150
151   for (ii=0; ii<n_apc; ii++) {
152     apc_n=tr_new_name(apc[ii]);
153     apc_entries=trp_rtable_get_apc_entries(table, apc_n, &n);
154     tr_free_name(apc_n);
155     assert(n==n_realm*n_peer);
156     while (n--) {
157       assert(0==strncmp(trp_rentry_get_apc(apc_entries[n])->buf,
158                         apc[ii],
159                         trp_rentry_get_apc(apc_entries[n])->len));
160       assert(1==is_in(trp_rentry_get_realm(apc_entries[n])->buf, realm, n_realm));
161       assert(1==is_in(trp_rentry_get_peer(apc_entries[n])->buf, peer, n_peer));
162     }
163     printf("APC %s ok!\n", apc[ii]);
164     talloc_free(apc_entries);
165   }
166 }
167
168 static void verify_get_realm_entries(TRP_RTABLE *table)
169 {
170   size_t n=0, ii=0, jj=0;
171   TRP_RENTRY **realm_entries=NULL;
172   TR_NAME *apc_n=NULL, *realm_n=NULL;
173
174   for (ii=0; ii<n_apc; ii++) {
175     for (jj=0; jj<n_realm; jj++) {
176       apc_n=tr_new_name(apc[ii]);
177       realm_n=tr_new_name(realm[jj]);
178       realm_entries=trp_rtable_get_realm_entries(table, apc_n, realm_n, &n);
179       tr_free_name(apc_n);
180       tr_free_name(realm_n);
181       assert(n==n_peer);
182       while (n--) {
183         assert(0==strncmp(trp_rentry_get_apc(realm_entries[n])->buf,
184                           apc[ii],
185                           trp_rentry_get_apc(realm_entries[n])->len));
186         assert(0==strncmp(trp_rentry_get_realm(realm_entries[n])->buf,
187                           realm[jj],
188                           trp_rentry_get_realm(realm_entries[n])->len));
189         assert(1==is_in(trp_rentry_get_peer(realm_entries[n])->buf, peer, n_peer));
190       }
191       printf("APC %s realm %s ok!\n", apc[ii], realm[jj]);
192       talloc_free(realm_entries);
193     }
194   }
195 }
196
197 /* doesn't work if c not in a */
198 static size_t get_index(char *c, char **a, size_t n_a)
199 {
200   while(n_a--) {
201     if (0==strcmp(c, a[n_a]))
202       return n_a;
203   }
204   return 0;
205 }
206
207 static void update_metric(TRP_RTABLE *table, unsigned int (*new_metric)(size_t, size_t, size_t))
208 {
209   TRP_RENTRY **entries=NULL;
210   size_t n=0, ii=0,jj=0,kk=0;
211
212   entries=trp_rtable_get_entries(table, &n);
213   while (n--) {
214     ii=get_index(trp_rentry_get_apc(entries[n])->buf, apc, n_apc);
215     jj=get_index(trp_rentry_get_realm(entries[n])->buf, realm, n_realm);
216     kk=get_index(trp_rentry_get_peer(entries[n])->buf, peer, n_peer);
217     trp_rentry_set_metric(entries[n],
218                           new_metric(ii,jj,kk));
219   }
220   talloc_free(entries);
221 }
222
223 static void remove_entries(TRP_RTABLE *table)
224 {
225   size_t n=trp_rtable_size(table);
226   size_t ii,jj,kk;
227   TR_NAME *apc_n, *realm_n, *peer_n;
228   TRP_RENTRY *entry=NULL;
229
230   for (ii=0; ii<n_apc; ii++) {
231     for (jj=0; jj<n_realm; jj++) {
232       for (kk=0; kk<n_realm; kk++) {
233         apc_n=tr_new_name(apc[ii]);
234         realm_n=tr_new_name(realm[jj]);
235         peer_n=tr_new_name(peer[kk]);
236         entry=trp_rtable_get_entry(table, apc_n, realm_n, peer_n);
237         assert(entry !=NULL);
238         tr_free_name(apc_n);
239         tr_free_name(realm_n);
240         tr_free_name(peer_n);
241         trp_rtable_remove(table, entry);
242         entry=NULL;
243         assert(trp_rtable_size(table)==--n);
244       }
245     }
246   }
247 }
248
249
250 static void print_rtable(TRP_RTABLE *table)
251 {
252   char *s=trp_rtable_to_str(NULL, table, NULL, NULL);
253   printf(s);
254   talloc_free(s);
255 }
256
257 int main(void)
258 {
259   TRP_RTABLE *table=NULL;
260   table=trp_rtable_new();
261   populate_rtable(table, metric1);
262   print_rtable(table);
263
264   printf("\nVerifying routing table...\n");
265   verify_rtable(table, metric1);
266   printf("                         ...success!\n");
267
268   printf("\nVerifying APC list...\n");
269   verify_apc_list(table);
270   printf("                    ...success!\n");
271
272   printf("\nVerifying APC realm lists...\n");
273   verify_apc_realm_lists(table);
274   printf("                    ...success!\n");
275
276   printf("\nVerifying APC entry lists...\n");
277   verify_get_apc_entries(table);
278   printf("                           ...success!\n");
279
280   printf("\nVerifying realm entry lists...\n");
281   verify_get_realm_entries(table);
282   printf("                              ...success!\n");
283
284   printf("\nVerifying table value update...\n");
285   update_metric(table, metric2); /* changes the metric value in each element in-place */
286   verify_rtable(table, metric2);
287   printf("                              ...success!\n");
288
289   printf("\nVerifying element replacement...\n");
290   populate_rtable(table, metric3); /* replaces all the elements with new ones */
291   verify_rtable(table, metric3);
292   printf("                               ...success!\n");
293
294   printf("\nVerifying element removal...\n");
295   remove_entries(table);
296   print_rtable(table);
297   printf("                           ...success!\n");
298
299   printf("\nRepopulating table...\n");
300   populate_rtable(table, metric3);
301   verify_rtable(table, metric3);
302   printf("                               ...success!\n");
303
304   trp_rtable_free(table);
305   return 0;
306 }