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