- backport fix to mesh_new
[oweals/gnunet.git] / src / mesh / test_mesh_tree_api.c
1 /*
2      This file is part of GNUnet.
3      (C) 2011 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file mesh/test_mesh_tree_api.c
23  * @brief test mesh tree api: test of tree & path management api
24  * @author Bartlomiej Polot
25  */
26
27 #include "platform.h"
28 #include "gnunet_common.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet_dht_service.h"
31 #include "gnunet_mesh_service.h"
32 #include "mesh.h"
33 #ifndef MESH_TUNNEL_TREE_C
34 #include "mesh_tunnel_tree.c"
35 #define MESH_TUNNEL_TREE_C
36 #endif
37
38 static int failed;
39 static int cb_call;
40 static struct GNUNET_PeerIdentity *pi[10];
41 static struct MeshTunnelTree *tree;
42
43 static void
44 cb (void *cls, GNUNET_PEER_Id peer_id)
45 {
46   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: CB: Disconnected %u\n", peer_id);
47   if (0 == cb_call)
48   {
49     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test:      and it shouldn't!\n");
50     failed++;
51   }
52   cb_call--;
53 }
54
55
56 /**
57  * Check if a node has all expected properties.
58  *
59  * @param peer_id Short ID of the peer to test.
60  * @param status Expected status of the peer.
61  * @param children Expected number of children of the peer.
62  * @param first_hop Short ID of the expected first hop towards the peer.
63  */
64 static void
65 test_assert (GNUNET_PEER_Id peer_id, enum MeshPeerState status,
66              unsigned int children, GNUNET_PEER_Id first_hop)
67 {
68   struct MeshTunnelTreeNode *n;
69   struct MeshTunnelTreeNode *c;
70   unsigned int i;
71   int pre_failed;
72
73   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Checking peer %u\n", peer_id);
74   pre_failed = failed;
75   n = tree_find_peer (tree, peer_id);
76   if (n->peer != peer_id)
77   {
78     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
79                 "Retrieved peer has wrong ID! (Got %u, expected %u)\n", n->peer,
80                 peer_id);
81     failed++;
82   }
83   if (n->status != status)
84   {
85     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
86                 "Retrieved peer has wrong status! (Got %u, expected %u)\n",
87                 n->status, status);
88     failed++;
89   }
90   for (c = n->children_head, i = 0; NULL != c; c = c->next, i++) ;
91   if (i != children)
92   {
93     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
94                 "Retrieved peer wrong has number of children! (Got %u, expected %u)\n",
95                 i, children);
96     failed++;
97   }
98   if (0 != first_hop &&
99       GNUNET_PEER_search (tree_get_first_hop (tree, peer_id)) != first_hop)
100   {
101     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
102                 "Wrong first hop! (Got %u, expected %u)\n",
103                 GNUNET_PEER_search (tree_get_first_hop (tree, peer_id)),
104                 first_hop);
105     failed++;
106   }
107   if (pre_failed != failed)
108   {
109     struct GNUNET_PeerIdentity id;
110
111     GNUNET_PEER_resolve (peer_id, &id);
112     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
113                 "*** Peer %s (%u) has failed %d checks!\n", GNUNET_i2s (&id),
114                 peer_id, failed - pre_failed);
115   }
116 }
117
118
119 static void
120 finish (void)
121 {
122   unsigned int i;
123
124   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Finishing...\n");
125   for (i = 0; i < 10; i++)
126   {
127     GNUNET_free (pi[i]);
128   }
129 }
130
131 /**
132  * Convert an integer int to a peer identity
133  */
134 static struct GNUNET_PeerIdentity *
135 get_pi (uint32_t id)
136 {
137   struct GNUNET_PeerIdentity *pi;
138
139   pi = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
140   pi->hashPubKey.bits[0] = id + 1;
141   return pi;
142 }
143
144
145 int
146 main (int argc, char *argv[])
147 {
148   struct MeshTunnelTreeNode *node;
149   struct MeshPeerPath *path;
150   struct MeshPeerPath *path1;
151   unsigned int i;
152
153   failed = 0;
154   cb_call = 0;
155   GNUNET_log_setup ("test_mesh_api_tree",
156                     "WARNING",
157                     NULL);
158   for (i = 0; i < 10; i++)
159   {
160     pi[i] = get_pi (i);
161     GNUNET_break (i + 1 == GNUNET_PEER_intern (pi[i]));
162     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u: %s\n", i + 1,
163                 GNUNET_h2s (&pi[i]->hashPubKey));
164   }
165   tree = tree_new (1);
166   tree->me = tree->root;
167   path = path_new (5);
168   path->peers[0] = 1;
169   path->peers[1] = 2;
170   path->peers[2] = 3;
171   path->peers[3] = 4;
172   path->length = 4;
173
174   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding first path: 1 2 3 4\n");
175   tree_add_path (tree, path, &cb, NULL);
176   tree_debug (tree);
177   path1 = tree_get_path_to_peer (tree, 4);
178   if (NULL == path1 || path->length != path1->length ||
179       memcmp (path->peers, path1->peers, path->length) != 0)
180   {
181     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Retrieved path != original\n");
182     failed++;
183   }
184   path_destroy (path1);
185   test_assert (4, MESH_PEER_SEARCHING, 0, 2);
186   test_assert (3, MESH_PEER_RELAY, 1, 0);
187   test_assert (2, MESH_PEER_RELAY, 1, 0);
188   test_assert (1, MESH_PEER_ROOT, 1, 0);
189
190   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding second path: 1 2 3\n");
191   path->length--;
192   tree_add_path (tree, path, &cb, NULL);
193   tree_debug (tree);
194
195   test_assert (4, MESH_PEER_SEARCHING, 0, 2);
196   test_assert (3, MESH_PEER_SEARCHING, 1, 2);
197   test_assert (2, MESH_PEER_RELAY, 1, 0);
198   test_assert (1, MESH_PEER_ROOT, 1, 0);
199
200   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding third path 1 2 3 5\n");
201   path->length++;
202   path->peers[3] = 5;
203   tree_add_path (tree, path, &cb, NULL);
204   tree_debug (tree);
205
206   test_assert (5, MESH_PEER_SEARCHING, 0, 2);
207   test_assert (4, MESH_PEER_SEARCHING, 0, 2);
208   test_assert (3, MESH_PEER_SEARCHING, 2, 2);
209   test_assert (2, MESH_PEER_RELAY, 1, 0);
210   test_assert (1, MESH_PEER_ROOT, 1, 0);
211
212   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Calculating costs...\n");
213   for (i = 1; i < 5; i++)
214   {
215     path->length = i;
216     if (tree_get_path_cost (tree, path) != 0)
217     {
218       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: length %u cost failed!\n",
219                   i);
220       failed++;
221     }
222   }
223   path->length++;
224   path->peers[4] = 6;
225   if (tree_get_path_cost (tree, path) != 1)
226   {
227     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: length %u cost failed!\n", i);
228     failed++;
229   }
230   path->peers[3] = 7;
231   if (tree_get_path_cost (tree, path) != 2)
232   {
233     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: length %u cost failed!\n", i);
234     failed++;
235   }
236   path->length--;
237   if (tree_get_path_cost (tree, path) != 1)
238   {
239     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: length %u cost failed!\n", i);
240     failed++;
241   }
242   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Deleting third path (5)\n");
243   tree_set_status (tree, 5, MESH_PEER_READY);
244   cb_call = 1;
245   node = tree_del_path (tree, 5, &cb, NULL);
246   tree_debug (tree);
247   if (cb_call != 0)
248   {
249     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%u callbacks missed!\n", cb_call);
250     failed++;
251   }
252   if (node->peer != 5)
253   {
254     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Retrieved peer != original\n");
255     failed++;
256   }
257
258   test_assert (4, MESH_PEER_SEARCHING, 0, 2);
259   test_assert (3, MESH_PEER_SEARCHING, 1, 2);
260   test_assert (2, MESH_PEER_RELAY, 1, 0);
261   test_assert (1, MESH_PEER_ROOT, 1, 0);
262
263   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Destroying node copy...\n");
264   GNUNET_free (node);
265
266   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
267               "test: Adding new shorter first path...\n");
268   path->length = 2;
269   path->peers[1] = 4;
270   cb_call = 1;
271   tree_find_peer (tree, 4)->status = MESH_PEER_READY;
272   tree_add_path (tree, path, &cb, NULL);
273   tree_debug (tree);
274   if (cb_call != 0)
275   {
276     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%u callbacks missed!\n", cb_call);
277     failed++;
278   }
279
280   test_assert (4, MESH_PEER_SEARCHING, 0, 4);
281   test_assert (3, MESH_PEER_SEARCHING, 0, 2);
282   test_assert (2, MESH_PEER_RELAY, 1, 0);
283   test_assert (1, MESH_PEER_ROOT, 2, 0);
284
285   GNUNET_free (path->peers);
286   GNUNET_free (path);
287   tree_destroy (tree);
288
289   /****************************************************************************/
290
291   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test:\n");
292   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Testing relay trees\n");
293   for (i = 0; i < 10; i++)
294   {
295     GNUNET_break (i + 1 == GNUNET_PEER_intern (pi[i]));
296   }
297   tree = tree_new (2);
298   path = path_new (8);
299   path->peers[0] = 2;
300   path->peers[1] = 1;
301   path->peers[2] = 3;
302   path->length = 3;
303
304   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding first path: 2 1 3\n");
305   tree_add_path (tree, path, &cb, NULL);
306   tree_debug (tree);
307
308   test_assert (3, MESH_PEER_SEARCHING, 0, 3);
309   test_assert (1, MESH_PEER_RELAY, 1, 0);
310   test_assert (2, MESH_PEER_ROOT, 1, 0);
311
312   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding long path: 2 1 4 5 3\n");
313   path->peers[2] = 4;
314   path->peers[3] = 5;
315   path->peers[4] = 3;
316   path->length = 5;
317   tree_add_path (tree, path, &cb, NULL);
318   tree_debug (tree);
319
320   test_assert (3, MESH_PEER_SEARCHING, 0, 4);
321   test_assert (5, MESH_PEER_RELAY, 1, 4);
322   test_assert (4, MESH_PEER_RELAY, 1, 4);
323   test_assert (1, MESH_PEER_RELAY, 1, 0);
324   test_assert (2, MESH_PEER_ROOT, 1, 0);
325
326   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
327               "test: Even longer path: 2 6 1 7 8 4 5 3\n");
328   path->peers[0] = 2;
329   path->peers[1] = 6;
330   path->peers[2] = 1;
331   path->peers[3] = 7;
332   path->peers[4] = 8;
333   path->peers[5] = 4;
334   path->peers[6] = 5;
335   path->peers[7] = 3;
336   path->length = 8;
337   tree_add_path (tree, path, &cb, NULL);
338   tree_debug (tree);
339
340   test_assert (3, MESH_PEER_SEARCHING, 0, 7);
341   test_assert (5, MESH_PEER_RELAY, 1, 7);
342   test_assert (4, MESH_PEER_RELAY, 1, 7);
343   test_assert (8, MESH_PEER_RELAY, 1, 7);
344   test_assert (7, MESH_PEER_RELAY, 1, 7);
345   test_assert (1, MESH_PEER_RELAY, 1, 0);
346   test_assert (6, MESH_PEER_RELAY, 1, 0);
347   test_assert (2, MESH_PEER_ROOT, 1, 0);
348
349   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding first path: 2 1 3\n");
350   path->peers[1] = 1;
351   path->peers[2] = 3;
352   path->length = 3;
353   tree_add_path (tree, path, &cb, NULL);
354   tree_debug (tree);
355
356   test_assert (3, MESH_PEER_SEARCHING, 0, 3);
357   test_assert (1, MESH_PEER_RELAY, 1, 0);
358   test_assert (2, MESH_PEER_ROOT, 1, 0);
359
360   GNUNET_free (path->peers);
361   GNUNET_free (path);
362   tree_destroy (tree);
363   finish ();
364   if (failed > 0)
365   {
366     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%u tests failed\n", failed);
367     return 1;
368   }
369   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: OK\n");
370
371   return 0;
372 }