Test peer table and update selection functions. Seem to work.
[trust_router.git] / trp / test / ptbl_test.c
1 #include <stdio.h>
2 #include <talloc.h>
3 #include <assert.h>
4
5 #include <trp_internal.h>
6 #include <trp_ptable.h>
7
8 struct peer_entry {
9   char *server;
10   unsigned int port;
11   unsigned int linkcost;
12 };
13
14 static struct peer_entry peer_data[]={
15   {"peer0", 10000, 0x0001},
16   {"peer1", 15000, 0x0002},
17   {"peer2", 20000, 0x0004},
18   {"peer3", 25000, 0x0008},
19   {"peer4", 30000, 0x0010}
20 };
21 static size_t n_peers=sizeof(peer_data)/sizeof(peer_data[0]);
22
23 static void populate_ptable(TRPS_INSTANCE *trps)
24 {
25   TRP_PEER *new_peer;
26   int i;
27
28   for (i=0; i<n_peers; i++) {
29     new_peer=trp_peer_new(NULL);
30     assert(new_peer!=NULL);
31     trp_peer_set_server(new_peer, peer_data[i].server);
32     assert(trp_peer_get_server(new_peer)!=NULL);
33     trp_peer_set_port(new_peer, peer_data[i].port);
34     trp_peer_set_linkcost(new_peer, peer_data[i].linkcost);
35     assert(trps_add_peer(trps, new_peer)==TRP_SUCCESS);
36   }
37 }
38
39 static struct peer_entry *find_peer_entry(char *server)
40 {
41   int i;
42   for (i=0; i<n_peers; i++) {
43     if (0==strcmp(server, peer_data[i].server)) {
44       return (peer_data+i);
45     }
46   }
47   return NULL;
48 }
49
50 static void verify_ptable(TRPS_INSTANCE *trps)
51 {
52   struct peer_entry *peer_entry=NULL;
53   TRP_PEER *peer;
54   char *s;
55   TR_NAME *gssname;
56
57   peer=trps->ptable->head;
58   while (peer!=NULL) {
59     peer_entry=find_peer_entry(trp_peer_get_server(peer));
60     assert(peer_entry!=NULL);
61     assert(!strcmp(trp_peer_get_server(peer), peer_entry->server));
62     assert(trp_peer_get_port(peer)==peer_entry->port);
63     assert(trp_peer_get_linkcost(peer)==peer_entry->linkcost);
64     assert(0<asprintf(&s, "trustrouter@%s", peer_entry->server));
65     gssname=tr_new_name(s);
66     free(s);
67     assert(gssname!=NULL);
68     assert(!tr_name_cmp(trp_peer_get_gssname(peer), gssname));
69     tr_free_name(gssname);
70     peer=peer->next;
71   }
72 }
73
74 struct route_data {
75   char *apc;
76   char *realm;
77   char *peer;
78   unsigned int metric;
79   char *trust_router;
80   char *next_hop;
81   int selected;
82   unsigned int interval;
83   int verified; /* for testing */
84 };
85 static struct route_data route_table[]={
86   {"apc0", "realm0", "", 0, "tr.r0.apc0", "", 1, 60, 0},
87   {"apc0", "realm1", "", 0, "tr.r1.apc0", "", 1, 60, 0},
88   {"apc0", "realm0", "trustrouter@peer0", 1, "tr.r0.apc0", "trustrouter@peer0", 0, 60, 0},
89   {"apc0", "realm1", "trustrouter@peer0", 0, "tr.r1.apc0", "trustrouter@peer0", 0, 60, 0},
90   {"apc0", "realm2", "trustrouter@peer0", 0, "tr.r2.apc0", "trustrouter@peer0", 1, 60, 0},
91   {"apc0", "realm3", "trustrouter@peer0", 1, "tr.r3.apc0", "trustrouter@peer0", 0, 60, 0},
92   {"apc0", "realm4", "trustrouter@peer0", 2, "tr.r4.apc0", "trustrouter@peer0", 0, 60, 0},
93   {"apc0", "realm0", "trustrouter@peer1", 0, "tr.r0.apc0", "trustrouter@peer1", 0, 60, 0},
94   {"apc0", "realm1", "trustrouter@peer1", 1, "tr.r1.apc0", "trustrouter@peer1", 0, 60, 0},
95   {"apc0", "realm2", "trustrouter@peer1", 1, "tr.r2.apc0", "trustrouter@peer1", 0, 60, 0},
96   {"apc0", "realm3", "trustrouter@peer1", 0, "tr.r3.apc0", "trustrouter@peer1", 1, 60, 0},
97   {"apc0", "realm4", "trustrouter@peer1", 2, "tr.r4.apc0", "trustrouter@peer1", 0, 60, 0},
98   {"apc0", "realm0", "trustrouter@peer2", 0, "tr.r0.apc0", "trustrouter@peer2", 0, 60, 0},
99   {"apc0", "realm1", "trustrouter@peer2", 2, "tr.r1.apc0", "trustrouter@peer2", 0, 60, 0},
100   {"apc0", "realm2", "trustrouter@peer2", 2, "tr.r2.apc0", "trustrouter@peer2", 0, 60, 0},
101   {"apc0", "realm3", "trustrouter@peer2", 1, "tr.r3.apc0", "trustrouter@peer2", 0, 60, 0},
102   {"apc0", "realm4", "trustrouter@peer2", 0, "tr.r4.apc0", "trustrouter@peer2", 1, 60, 0},
103 };
104 static size_t n_routes=sizeof(route_table)/sizeof(route_table[0]);
105
106 /* These are the correct updates to select from the above route table for each peer.
107  * The rule is: send selected route unless it is through that peer, otherwise send
108  * the best (lowest metric) alternative route. 
109  *
110  * In a few cases there are multiple valid options (when a two non-selected routes
111  * exist). If these tests are failing, it may be that the trps code is selecting another
112  * valid option, so check that. Probably ought to tweak metrics to avoid that ambiguity. */
113 static struct route_data update_table[][10]={
114   { /* peer0 */
115     {"apc0", "realm0", "", 0, "tr.r0.apc0", "", 1, 60, 0},
116     {"apc0", "realm1", "", 0, "tr.r1.apc0", "", 1, 60, 0},
117     {"apc0", "realm2", "trustrouter@peer1", 1, "tr.r2.apc0", "trustrouter@peer1", 0, 60, 0},
118     {"apc0", "realm3", "trustrouter@peer1", 0, "tr.r3.apc0", "trustrouter@peer1", 1, 60, 0},
119     {"apc0", "realm4", "trustrouter@peer2", 0, "tr.r4.apc0", "trustrouter@peer2", 1, 60, 0},
120     {NULL}
121   },
122   { /* peer1 */
123     {"apc0", "realm0", "", 0, "tr.r0.apc0", "", 1, 60, 0},
124     {"apc0", "realm1", "", 0, "tr.r1.apc0", "", 1, 60, 0},
125     {"apc0", "realm2", "trustrouter@peer0", 0, "tr.r2.apc0", "trustrouter@peer0", 1, 60, 0},
126     {"apc0", "realm3", "trustrouter@peer2", 1, "tr.r3.apc0", "trustrouter@peer2", 0, 60, 0},
127     {"apc0", "realm4", "trustrouter@peer2", 0, "tr.r4.apc0", "trustrouter@peer2", 1, 60, 0},
128     {NULL}
129   },
130   { /* peer2 */
131     {"apc0", "realm0", "", 0, "tr.r0.apc0", "", 1, 60, 0},
132     {"apc0", "realm1", "", 0, "tr.r1.apc0", "", 1, 60, 0},
133     {"apc0", "realm2", "trustrouter@peer0", 0, "tr.r2.apc0", "trustrouter@peer0", 1, 60, 0},
134     {"apc0", "realm3", "trustrouter@peer1", 0, "tr.r3.apc0", "trustrouter@peer1", 1, 60, 0},
135     {"apc0", "realm4", "trustrouter@peer1", 2, "tr.r4.apc0", "trustrouter@peer1", 0, 60, 0},
136     {NULL}
137   },
138   { /* peer3 */
139     {"apc0", "realm0", "", 0, "tr.r0.apc0", "", 1, 60, 0},
140     {"apc0", "realm1", "", 0, "tr.r1.apc0", "", 1, 60, 0},
141     {"apc0", "realm2", "trustrouter@peer0", 0, "tr.r2.apc0", "trustrouter@peer0", 1, 60, 0},
142     {"apc0", "realm3", "trustrouter@peer1", 0, "tr.r3.apc0", "trustrouter@peer1", 1, 60, 0},
143     {"apc0", "realm4", "trustrouter@peer2", 0, "tr.r4.apc0", "trustrouter@peer2", 1, 60, 0},
144     {NULL}
145   },
146   { /* peer4 */
147     {"apc0", "realm0", "", 0, "tr.r0.apc0", "", 1, 60, 0},
148     {"apc0", "realm1", "", 0, "tr.r1.apc0", "", 1, 60, 0},
149     {"apc0", "realm2", "trustrouter@peer0", 0, "tr.r2.apc0", "trustrouter@peer0", 1, 60, 0},
150     {"apc0", "realm3", "trustrouter@peer1", 0, "tr.r3.apc0", "trustrouter@peer1", 1, 60, 0},
151     {"apc0", "realm4", "trustrouter@peer2", 0, "tr.r4.apc0", "trustrouter@peer2", 1, 60, 0},
152     {NULL}
153   }
154 };
155
156 static void populate_rtable(TRPS_INSTANCE *trps)
157 {
158   int i;
159   TRP_RENTRY *new;
160
161   for (i=0; i<n_routes; i++) {
162     new=trp_rentry_new(NULL);
163     assert(new!=NULL);
164     trp_rentry_set_apc(new, tr_new_name(route_table[i].apc));
165     trp_rentry_set_realm(new, tr_new_name(route_table[i].realm));
166     trp_rentry_set_peer(new, tr_new_name(route_table[i].peer));
167     trp_rentry_set_metric(new, route_table[i].metric);
168     trp_rentry_set_trust_router(new, tr_new_name(route_table[i].trust_router));
169     trp_rentry_set_next_hop(new, tr_new_name(route_table[i].next_hop));
170     trp_rentry_set_selected(new, route_table[i].selected);
171     trp_rentry_set_interval(new, route_table[i].interval);
172     /* do not set expiry */
173     trp_rtable_add(trps->rtable, new);
174     new=NULL;
175   }
176 }
177
178 static void verify_update(TRP_RENTRY **updates, size_t n_updates, struct route_data *expected)
179 {
180   int ii,jj;
181   int found;
182
183   for(jj=0; jj<n_updates; jj++) {
184     found=0;
185     for (ii=0; expected[ii].apc!=NULL; ii++) {
186       if ((0==strcmp(expected[ii].apc, updates[jj]->apc->buf))
187          &&(0==strcmp(expected[ii].realm, updates[jj]->realm->buf))
188          &&(0==strcmp(expected[ii].peer, updates[jj]->peer->buf))
189          &&(expected[ii].metric==updates[jj]->metric)
190          &&(0==strcmp(expected[ii].trust_router, updates[jj]->trust_router->buf))
191          &&(0==strcmp(expected[ii].next_hop, updates[jj]->next_hop->buf))
192          &&(expected[ii].selected==updates[jj]->selected)
193          &&(expected[ii].interval==updates[jj]->interval)) {
194         assert(expected[ii].verified==0); /* should only encounter each entry once */
195         expected[ii].verified=1;
196         found=1;
197         continue;
198       }
199     }
200     if (!found) {
201       printf("missing:\n%s\n", trp_rentry_to_str(NULL,updates[jj], " | "));
202       assert(0);
203     }
204   }
205   for(ii=0; expected[ii].apc!=NULL; ii++)
206     assert(expected[ii].verified==1);
207 }
208
209 static void verify_update_selection(TRPS_INSTANCE *trps)
210 {
211   int ii;
212   TRP_RENTRY **updates=NULL;
213   size_t n_updates;
214   TR_NAME *gssname=NULL;
215   char *s;
216
217   for (ii=0; ii<n_peers; ii++) {
218     assert(0<asprintf(&s, "trustrouter@%s", peer_data[ii].server));
219     assert(NULL!=(gssname=tr_new_name(s)));
220     free(s);
221     updates=trps_select_updates_for_peer(NULL, trps, gssname, &n_updates);
222     tr_free_name(gssname);
223     verify_update(updates, n_updates, update_table[ii]);
224     talloc_free(updates);
225   }
226 }
227
228 int main(void)
229 {
230   TALLOC_CTX *main_ctx=talloc_new(NULL);
231   TRPS_INSTANCE *trps;
232   char *s;
233
234   trps=trps_new(main_ctx);
235
236   printf("\nPopulating peer table...\n");
237   populate_ptable(trps);
238
239   printf("\nVerifying peer table...\n");
240   verify_ptable(trps);
241
242   printf("\nPopulating route table...\n");
243   populate_rtable(trps);
244   s=trp_rtable_to_str(main_ctx, trps->rtable, " | ", NULL);
245   printf("Route Table:\n%s---\n", s);
246
247   printf("\nVerifying route update selection...\n");
248   verify_update_selection(trps);
249
250   printf("\nDone\n\n");
251   talloc_report_full(main_ctx, stderr);
252   talloc_free(main_ctx);
253   talloc_report_full(NULL, stderr);
254   return 0;
255 }