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