Fixed id counters' cycling
[oweals/gnunet.git] / src / mesh / test_mesh_path_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_path.c
23  * @brief test mesh path: test of 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 #include "mesh_tunnel_tree.h"
34
35 #define VERBOSE 1
36
37 int failed;
38 int cb_call;
39 struct GNUNET_PeerIdentity* pi[10];
40 struct MeshTunnelTree *tree;
41
42 static void
43 cb (const struct MeshTunnelTreeNode *n)
44 {
45   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: CB: Disconnected %u\n", n->peer);
46   if(0 == cb_call)
47   {
48     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test:      and it shouldn't!\n");
49     failed++;
50   }
51   cb_call--;
52 }
53
54
55 /**
56  * Check if a node has all expected properties.
57  *
58  * @param peer_id Short ID of the peer to test.
59  * @param status Expected status of the peer.
60  * @param children Expected number of children of the peer.
61  * @param first_hop Short ID of the expected first hop towards the peer.
62  */
63 static void
64 test_assert (GNUNET_PEER_Id peer_id,
65              enum MeshPeerState status,
66              unsigned int children,
67              GNUNET_PEER_Id first_hop)
68 {
69   struct MeshTunnelTreeNode *n;
70   struct MeshTunnelTreeNode *c;
71   unsigned int i;
72   int pre_failed;
73
74   pre_failed = failed;
75   n = tree_find_peer(tree->root, peer_id);
76   if (n->peer != peer_id)
77   {
78     GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
79                "Retrieved peer != original (%u, %u)\n",
80                n->peer, peer_id);
81     failed++;
82   }
83   if (n->status != status)
84   {
85     GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
86                "Retrieved peer has wrong status! (%u, %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! (%u, %u)\n",
95                i, children);
96     failed++;
97   }
98   if (0 != first_hop &&
99       GNUNET_PEER_search(path_get_first_hop(tree, peer_id)) != first_hop)
100   {
101     GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
102                "Wrong first hop! (%u, %u)\n",
103                GNUNET_PEER_search(path_get_first_hop(tree, peer_id)),
104                first_hop);
105     failed++;
106   }
107   if (pre_failed != failed)
108   {
109     struct GNUNET_PeerIdentity id;
110     GNUNET_PEER_resolve (peer_id, &id);
111     GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
112                "*** Peer %s (%u) has failed %d checks! (real, expected)\n",
113                GNUNET_i2s (&id), peer_id,  failed - pre_failed);
114   }
115 }
116
117
118 static void
119 finish(void)
120 {
121   unsigned int i;
122
123   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: Finishing...\n");
124   for (i = 0; i < 10; i++)
125   {
126     GNUNET_free(pi[i]);
127   }
128   exit(0);
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 MeshTunnelTreeNode *node2;
150   struct MeshPeerPath *path;
151   struct MeshPeerPath *path1;
152   unsigned int i;
153
154   failed = 0;
155   cb_call = 0;
156   GNUNET_log_setup ("test_mesh_api_path",
157 #if VERBOSE
158                     "DEBUG",
159 #else
160                     "WARNING",
161 #endif
162                     NULL);
163   for (i = 0; i < 10; i++)
164   {
165       pi[i] = get_pi(i);
166       GNUNET_break (i + 1 == GNUNET_PEER_intern(pi[i]));
167       GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Peer %u: %s\n",
168                  i + 1,
169                  GNUNET_h2s(&pi[i]->hashPubKey));
170   }
171   tree = GNUNET_malloc(sizeof(struct MeshTunnelTree));
172   tree->first_hops = GNUNET_CONTAINER_multihashmap_create(32);
173   tree->root = GNUNET_malloc(sizeof(struct MeshTunnelTreeNode));
174   tree->root->peer = 1;
175   tree->me = tree->root;
176   path = path_new (4);
177   path->peers[0] = 1;
178   path->peers[1] = 2;
179   path->peers[2] = 3;
180   path->peers[3] = 4;
181   path->length = 4;
182
183   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: Adding first path: 1 2 3 4\n");
184   tree_add_path(tree, path, &cb);
185   tree_debug(tree);
186   path1 = tree_get_path_to_peer(tree, 4);
187   if (path->length != path1->length ||
188       memcmp(path->peers, path1->peers, path->length) != 0)
189   {
190     GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Retrieved path != original\n");
191     failed++;
192   }
193   path_destroy(path1);
194   test_assert (4, MESH_PEER_SEARCHING, 0, 2);
195   test_assert (3, MESH_PEER_RELAY, 1, 0);
196   test_assert (2, MESH_PEER_RELAY, 1, 0);
197   test_assert (1, MESH_PEER_ROOT, 1, 0);
198
199   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: Adding second path: 1 2 3\n");
200   path->length--;
201   tree_add_path(tree, path, &cb);
202   tree_debug(tree);
203
204   test_assert (4, MESH_PEER_SEARCHING, 0, 2);
205   test_assert (3, MESH_PEER_SEARCHING, 1, 2);
206   test_assert (2, MESH_PEER_RELAY, 1, 0);
207   test_assert (1, MESH_PEER_ROOT, 1, 0);
208
209   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: Adding third path...\n");
210   path->length++;
211   path->peers[3] = 5;
212   tree_add_path(tree, path, &cb);
213   tree_debug(tree);
214
215   test_assert (5, MESH_PEER_SEARCHING, 0, 2);
216   test_assert (4, MESH_PEER_SEARCHING, 0, 2);
217   test_assert (3, MESH_PEER_SEARCHING, 2, 2);
218   test_assert (2, MESH_PEER_RELAY, 1, 0);
219   test_assert (1, MESH_PEER_ROOT, 1, 0);
220
221   node = tree_find_peer(tree->root, 5);
222   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: Deleting third path...\n");
223   node->status = MESH_PEER_READY;
224   cb_call = 1;
225   node2 = tree_del_path(tree, 5, &cb);
226   tree_debug(tree);
227   if (cb_call != 0)
228   {
229     GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%u callbacks missed!\n", cb_call);
230     failed++;
231   }
232   if (node2->peer != 5)
233   {
234     GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Retrieved peer != original\n");
235     failed++;
236   }
237
238   test_assert (4, MESH_PEER_SEARCHING, 0, 2);
239   test_assert (3, MESH_PEER_SEARCHING, 1, 2);
240   test_assert (2, MESH_PEER_RELAY, 1, 0);
241   test_assert (1, MESH_PEER_ROOT, 1, 0);
242
243   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: Destroying node copy...\n");
244   GNUNET_free (node2);
245
246   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
247              "test: Adding new shorter first path...\n");
248   path->length = 2;
249   path->peers[1] = 4;
250   cb_call = 1;
251   tree_find_peer(tree->root, 4)->status = MESH_PEER_READY;
252   tree_add_path(tree, path, cb);
253   tree_debug(tree);
254   if (cb_call != 0)
255   {
256     GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%u callbacks missed!\n", cb_call);
257     failed++;
258   }
259
260   test_assert (4, MESH_PEER_SEARCHING, 0, 4);
261   test_assert (3, MESH_PEER_SEARCHING, 0, 2);
262   test_assert (2, MESH_PEER_RELAY, 1, 0);
263   test_assert (1, MESH_PEER_ROOT, 2, 0);
264
265   GNUNET_free (path->peers);
266   GNUNET_free (path);
267   tree_destroy (tree);
268
269   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test:\n");
270   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: Testing relay trees\n");
271   for (i = 0; i < 10; i++)
272   {
273       pi[i] = get_pi(i);
274       GNUNET_break (i + 1 == GNUNET_PEER_intern(pi[i]));
275       GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Peer %u: %s\n",
276                  i + 1,
277                  GNUNET_h2s(&pi[i]->hashPubKey));
278   }
279   tree = GNUNET_malloc(sizeof(struct MeshTunnelTree));
280   tree->first_hops = GNUNET_CONTAINER_multihashmap_create(32);
281   tree->root = GNUNET_malloc(sizeof(struct MeshTunnelTreeNode));
282   tree->root->peer = 1;
283   path = path_new (3);
284   path->peers[0] = 1;
285   path->peers[1] = 2;
286   path->peers[2] = 3;
287   path->length = 3;
288
289   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: Adding first path: 1 2 3\n");
290   tree_add_path(tree, path, &cb);
291   tree_debug(tree);
292   tree->me = tree_find_peer (tree->root, 2);
293
294   test_assert (3, MESH_PEER_SEARCHING, 0, 3);
295   test_assert (2, MESH_PEER_RELAY, 1, 0);
296   test_assert (1, MESH_PEER_ROOT, 1, 0);
297
298   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: Adding same path: 1 2 3\n");
299   tree_add_path(tree, path, &cb);
300   
301   GNUNET_free (path->peers);
302   GNUNET_free (path);
303   tree_destroy (tree);
304
305   if (failed > 0)
306   {
307     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%u tests failed\n", failed);
308     return 1;
309   }
310   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: OK\n");
311   finish();
312   
313   return 0;
314 }