diff options
Diffstat (limited to 'src/dht/test_dht_topo.c')
-rw-r--r-- | src/dht/test_dht_topo.c | 674 |
1 files changed, 185 insertions, 489 deletions
diff --git a/src/dht/test_dht_topo.c b/src/dht/test_dht_topo.c index a4765ee89..0934d7abd 100644 --- a/src/dht/test_dht_topo.c +++ b/src/dht/test_dht_topo.c | |||
@@ -19,83 +19,59 @@ | |||
19 | */ | 19 | */ |
20 | /** | 20 | /** |
21 | * @file dht/test_dht_topo.c | 21 | * @file dht/test_dht_topo.c |
22 | * | 22 | * @author Christian Grothoff |
23 | * @brief Test for the dht service: store and retrieve in various topologies. | 23 | * @brief Test for the dht service: store and retrieve in various topologies. |
24 | * Each peer stores it own ID in the DHT and then a different peer tries to | 24 | * Each peer stores a value from the DHT and then each peer tries to get each |
25 | * retrieve that key from it. The GET starts after a first round of PUTS has | 25 | * value from each other peer. |
26 | * been made. Periodically, each peer stores its ID into the DHT. If after | ||
27 | * a timeout no result has been returned, the test fails. | ||
28 | */ | 26 | */ |
29 | #include "platform.h" | 27 | #include "platform.h" |
30 | #include "gnunet_testing_lib.h" | 28 | #include "gnunet_util_lib.h" |
31 | #include "gnunet_dht_service.h" | 29 | #include "gnunet_dht_service.h" |
32 | 30 | #include "dht_test_lib.h" | |
33 | #define REMOVE_DIR GNUNET_YES | ||
34 | 31 | ||
35 | /** | 32 | /** |
36 | * DIFFERENT TESTS TO RUN | 33 | * Number of peers to run. |
37 | */ | 34 | */ |
38 | #define LINE 0 | 35 | #define NUM_PEERS 5 |
39 | #define TORUS 1 | ||
40 | 36 | ||
41 | /** | 37 | /** |
42 | * How long until we give up on connecting the peers? | 38 | * How long until we give up on fetching the data? |
43 | */ | 39 | */ |
44 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1500) | ||
45 | |||
46 | #define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) | 40 | #define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) |
47 | 41 | ||
48 | #define PUT_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) | ||
49 | |||
50 | /** | 42 | /** |
51 | * Result of the test. | 43 | * How frequently do we execute the PUTs? |
52 | */ | 44 | */ |
53 | static int ok; | 45 | #define PUT_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) |
54 | 46 | ||
55 | /** | ||
56 | * Total number of peers in the test. | ||
57 | */ | ||
58 | static unsigned long long num_peers; | ||
59 | 47 | ||
60 | /** | 48 | /** |
61 | * Global configuration file | 49 | * Information we keep for each GET operation. |
62 | */ | 50 | */ |
63 | static struct GNUNET_CONFIGURATION_Handle *testing_cfg; | 51 | struct GetOperation |
52 | { | ||
53 | /** | ||
54 | * DLL. | ||
55 | */ | ||
56 | struct GetOperation *next; | ||
64 | 57 | ||
65 | /** | 58 | /** |
66 | * Total number of currently running peers. | 59 | * DLL. |
67 | */ | 60 | */ |
68 | static unsigned long long peers_running; | 61 | struct GetOperation *prev; |
69 | 62 | ||
70 | /** | 63 | /** |
71 | * Total number of connections in the whole network. | 64 | * Handle for the operation. |
72 | */ | 65 | */ |
73 | static unsigned int total_connections; | 66 | struct GNUNET_DHT_GetHandle *get; |
74 | 67 | ||
75 | /** | 68 | }; |
76 | * The currently running peer group. | ||
77 | */ | ||
78 | static struct GNUNET_TESTING_PeerGroup *pg; | ||
79 | 69 | ||
80 | /** | ||
81 | * File to report results to. | ||
82 | */ | ||
83 | static struct GNUNET_DISK_FileHandle *output_file; | ||
84 | 70 | ||
85 | /** | 71 | /** |
86 | * File to log connection info, statistics to. | 72 | * Result of the test. |
87 | */ | ||
88 | static struct GNUNET_DISK_FileHandle *data_file; | ||
89 | |||
90 | /** | ||
91 | * Task called to disconnect peers. | ||
92 | */ | ||
93 | static GNUNET_SCHEDULER_TaskIdentifier disconnect_task; | ||
94 | |||
95 | /** | ||
96 | * Task To perform tests | ||
97 | */ | 73 | */ |
98 | static GNUNET_SCHEDULER_TaskIdentifier test_task; | 74 | static int ok = 1; |
99 | 75 | ||
100 | /** | 76 | /** |
101 | * Task to do DHT_puts | 77 | * Task to do DHT_puts |
@@ -103,454 +79,208 @@ static GNUNET_SCHEDULER_TaskIdentifier test_task; | |||
103 | static GNUNET_SCHEDULER_TaskIdentifier put_task; | 79 | static GNUNET_SCHEDULER_TaskIdentifier put_task; |
104 | 80 | ||
105 | /** | 81 | /** |
106 | * Task called to shutdown test. | 82 | * Task to time out / regular shutdown. |
107 | */ | 83 | */ |
108 | static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle; | 84 | static GNUNET_SCHEDULER_TaskIdentifier timeout_task; |
109 | |||
110 | static char *topology_file; | ||
111 | |||
112 | static struct GNUNET_DHT_Handle **hs; | ||
113 | |||
114 | static struct GNUNET_DHT_GetHandle *get_h; | ||
115 | |||
116 | static struct GNUNET_DHT_GetHandle *get_h_2; | ||
117 | |||
118 | static struct GNUNET_DHT_GetHandle *get_h_far; | ||
119 | |||
120 | static int found_1; | ||
121 | |||
122 | static int found_2; | ||
123 | |||
124 | static int found_far; | ||
125 | 85 | ||
126 | /** | 86 | /** |
127 | * Which topology are we to run | 87 | * Head of list of active GET operations. |
128 | */ | 88 | */ |
129 | static int test_topology; | 89 | static struct GetOperation *get_head; |
130 | |||
131 | 90 | ||
132 | /** | 91 | /** |
133 | * Check whether peers successfully shut down. | 92 | * Tail of list of active GET operations. |
134 | */ | 93 | */ |
135 | static void | 94 | static struct GetOperation *get_tail; |
136 | shutdown_callback (void *cls, const char *emsg) | ||
137 | { | ||
138 | if (emsg != NULL) | ||
139 | { | ||
140 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Shutdown of peers failed!\n"); | ||
141 | ok++; | ||
142 | } | ||
143 | else | ||
144 | { | ||
145 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All peers successfully shut down!\n"); | ||
146 | } | ||
147 | GNUNET_CONFIGURATION_destroy (testing_cfg); | ||
148 | } | ||
149 | 95 | ||
150 | 96 | ||
97 | /** | ||
98 | * Task run on success or timeout to clean up. | ||
99 | * Terminates active get operations and shuts down | ||
100 | * the testbed. | ||
101 | * | ||
102 | * @param cls the 'struct GNUNET_DHT_TestContext' | ||
103 | * @param tc scheduler context | ||
104 | */ | ||
151 | static void | 105 | static void |
152 | shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 106 | shutdown_task (void *cls, |
107 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
153 | { | 108 | { |
154 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Ending test.\n"); | 109 | struct GNUNET_DHT_TEST_Context *ctx = cls; |
110 | struct GetOperation *get_op; | ||
155 | 111 | ||
156 | if (disconnect_task != GNUNET_SCHEDULER_NO_TASK) | 112 | while (NULL != (get_op = get_tail)) |
157 | { | 113 | { |
158 | GNUNET_SCHEDULER_cancel (disconnect_task); | 114 | GNUNET_DHT_get_stop (get_op->get); |
159 | disconnect_task = GNUNET_SCHEDULER_NO_TASK; | 115 | GNUNET_CONTAINER_DLL_remove (get_head, |
116 | get_tail, | ||
117 | get_op); | ||
118 | GNUNET_free (get_op); | ||
160 | } | 119 | } |
161 | |||
162 | if (data_file != NULL) | ||
163 | GNUNET_DISK_file_close (data_file); | ||
164 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
165 | } | ||
166 | |||
167 | |||
168 | static void | ||
169 | disconnect_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
170 | { | ||
171 | unsigned int i; | ||
172 | |||
173 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "disconnecting peers\n"); | ||
174 | disconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
175 | GNUNET_SCHEDULER_cancel (put_task); | 120 | GNUNET_SCHEDULER_cancel (put_task); |
176 | if (NULL != get_h) | 121 | GNUNET_DHT_TEST_cleanup (ctx); |
177 | GNUNET_DHT_get_stop (get_h); | ||
178 | if (NULL != get_h_2) | ||
179 | GNUNET_DHT_get_stop (get_h_2); | ||
180 | if (NULL != get_h_far) | ||
181 | GNUNET_DHT_get_stop (get_h_far); | ||
182 | for (i = 0; i < num_peers; i++) | ||
183 | { | ||
184 | GNUNET_DHT_disconnect (hs[i]); | ||
185 | } | ||
186 | GNUNET_SCHEDULER_cancel (shutdown_handle); | ||
187 | shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
188 | } | 122 | } |
189 | 123 | ||
190 | 124 | ||
125 | /** | ||
126 | * Iterator called on each result obtained for a DHT | ||
127 | * operation that expects a reply | ||
128 | * | ||
129 | * @param cls closure with our 'struct GetOperation' | ||
130 | * @param exp when will this value expire | ||
131 | * @param key key of the result | ||
132 | * @param get_path peers on reply path (or NULL if not recorded) | ||
133 | * @param get_path_length number of entries in get_path | ||
134 | * @param put_path peers on the PUT path (or NULL if not recorded) | ||
135 | * @param put_path_length number of entries in get_path | ||
136 | * @param type type of the result | ||
137 | * @param size number of bytes in data | ||
138 | * @param data pointer to the result data | ||
139 | */ | ||
191 | static void | 140 | static void |
192 | dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, | 141 | dht_get_handler (void *cls, struct GNUNET_TIME_Absolute exp, |
193 | const struct GNUNET_HashCode * key, | 142 | const struct GNUNET_HashCode * key, |
194 | const struct GNUNET_PeerIdentity *get_path, | 143 | const struct GNUNET_PeerIdentity *get_path, |
195 | unsigned int get_path_length, | 144 | unsigned int get_path_length, |
196 | const struct GNUNET_PeerIdentity *put_path, | 145 | const struct GNUNET_PeerIdentity *put_path, |
197 | unsigned int put_path_length, enum GNUNET_BLOCK_Type type, | 146 | unsigned int put_path_length, enum GNUNET_BLOCK_Type type, |
198 | size_t size, const void *data) | 147 | size_t size, const void *data) |
199 | { | 148 | { |
200 | int i; | 149 | struct GetOperation *get_op = cls; |
201 | 150 | struct GNUNET_HashCode want; | |
202 | if (sizeof (struct GNUNET_HashCode) == size) | 151 | struct GNUNET_DHT_TestContext *ctx; |
203 | { | ||
204 | const struct GNUNET_HashCode *h = data; | ||
205 | |||
206 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Contents: %s\n", | ||
207 | GNUNET_h2s_full (h)); | ||
208 | 152 | ||
209 | } | 153 | if (sizeof (struct GNUNET_HashCode) != size) |
210 | else | ||
211 | { | ||
212 | GNUNET_break(0); | ||
213 | } | ||
214 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PATH: (get %u, put %u)\n", | ||
215 | get_path_length, put_path_length); | ||
216 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " LOCAL\n"); | ||
217 | for (i = get_path_length - 1; i >= 0; i--) | ||
218 | { | 154 | { |
219 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %s\n", | 155 | GNUNET_break (0); |
220 | GNUNET_i2s (&get_path[i])); | 156 | return; |
221 | } | 157 | } |
222 | for (i = put_path_length - 1; i >= 0; i--) | 158 | GNUNET_CRYPTO_hash (key, sizeof (*key), &want); |
159 | if (0 != memcmp (&want, data, sizeof (want))) | ||
223 | { | 160 | { |
224 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %s\n", | 161 | GNUNET_break (0); |
225 | GNUNET_i2s (&put_path[i])); | 162 | return; |
226 | } | 163 | } |
227 | switch ((long)cls) | 164 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
165 | "Get successful\n"); | ||
166 | #if 0 | ||
228 | { | 167 | { |
229 | case 1: | 168 | int i; |
230 | found_1++; | 169 | |
231 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "FOUND 1!\n"); | 170 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PATH: (get %u, put %u)\n", |
232 | break; | 171 | get_path_length, put_path_length); |
233 | case 2: | 172 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " LOCAL\n"); |
234 | found_2++; | 173 | for (i = get_path_length - 1; i >= 0; i--) |
235 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "FOUND 2!\n"); | 174 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %s\n", |
236 | break; | 175 | GNUNET_i2s (&get_path[i])); |
237 | case 3: | 176 | for (i = put_path_length - 1; i >= 0; i--) |
238 | found_far++; | 177 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %s\n", |
239 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "FOUND FAR!\n"); | 178 | GNUNET_i2s (&put_path[i])); |
240 | break; | ||
241 | default: | ||
242 | GNUNET_break(0); | ||
243 | } | 179 | } |
244 | if ( (TORUS == test_topology) && | 180 | #endif |
245 | ( (found_1 == 0) || (found_2 == 0) || (found_far == 0)) ) | 181 | GNUNET_DHT_get_stop (get_op->get); |
182 | GNUNET_CONTAINER_DLL_remove (get_head, | ||
183 | get_tail, | ||
184 | get_op); | ||
185 | GNUNET_free (get_op); | ||
186 | if (NULL != get_head) | ||
246 | return; | 187 | return; |
188 | /* all DHT GET operations successful; terminate! */ | ||
247 | ok = 0; | 189 | ok = 0; |
248 | GNUNET_SCHEDULER_cancel (disconnect_task); | 190 | ctx = GNUNET_SCHEDULER_cancel (timeout_task); |
249 | disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_peers, NULL); | 191 | timeout_task = GNUNET_SCHEDULER_add_now (&shutdown_task, ctx); |
250 | } | 192 | } |
251 | 193 | ||
252 | 194 | ||
253 | static void | ||
254 | do_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
255 | { | ||
256 | struct GNUNET_TESTING_Daemon *d; | ||
257 | struct GNUNET_TESTING_Daemon *d2; | ||
258 | struct GNUNET_TESTING_Daemon *d_far; | ||
259 | struct GNUNET_TESTING_Daemon *o; | ||
260 | struct GNUNET_TESTING_Daemon *aux; | ||
261 | const char *id_aux; | ||
262 | const char *id_origin = "FC74"; | ||
263 | const char *id_near = "9P6V"; | ||
264 | const char *id_near2 = "2GDS"; | ||
265 | const char *id_far = "KPST"; | ||
266 | unsigned int i; | ||
267 | |||
268 | d = d2 = d_far = o = NULL; | ||
269 | found_1 = found_2 = found_far = 0; | ||
270 | if (LINE == test_topology) | ||
271 | { | ||
272 | o = GNUNET_TESTING_daemon_get (pg, 0); | ||
273 | d = GNUNET_TESTING_daemon_get (pg, num_peers - 1); | ||
274 | } | ||
275 | else if (TORUS == test_topology) | ||
276 | { | ||
277 | for (i = 0; i < num_peers; i++) | ||
278 | { | ||
279 | aux = GNUNET_TESTING_daemon_get (pg, i); | ||
280 | id_aux = GNUNET_i2s (&aux->id); | ||
281 | if (strcmp (id_aux, id_origin) == 0) | ||
282 | o = aux; | ||
283 | if (strcmp (id_aux, id_far) == 0) | ||
284 | d_far = aux; | ||
285 | if (strcmp (id_aux, id_near) == 0) | ||
286 | d = aux; | ||
287 | if (strcmp (id_aux, id_near2) == 0) | ||
288 | d2 = aux; | ||
289 | } | ||
290 | if ((NULL == o) || (NULL == d) || (NULL == d2) || (NULL == d_far)) | ||
291 | { | ||
292 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
293 | "Peers not found (hostkey file changed?)\n"); | ||
294 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
295 | disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_peers, NULL); | ||
296 | return; | ||
297 | } | ||
298 | } | ||
299 | else | ||
300 | { | ||
301 | GNUNET_assert (0); | ||
302 | } | ||
303 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test_task\nfrom %s\n", | ||
304 | GNUNET_h2s_full (&o->id.hashPubKey)); | ||
305 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " looking for %s\n", | ||
306 | GNUNET_h2s_full (&d->id.hashPubKey)); | ||
307 | get_h = GNUNET_DHT_get_start (hs[0], | ||
308 | GNUNET_BLOCK_TYPE_TEST, /* type */ | ||
309 | &d->id.hashPubKey, /*key to search */ | ||
310 | 4U, /* replication level */ | ||
311 | GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | ||
312 | NULL, /* xquery */ | ||
313 | 0, /* xquery bits */ | ||
314 | &dht_get_id_handler, (void *)1); | ||
315 | if (TORUS == test_topology) | ||
316 | { | ||
317 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " looking for %s\n", | ||
318 | GNUNET_h2s_full (&d2->id.hashPubKey)); | ||
319 | get_h_2 = GNUNET_DHT_get_start (hs[0], | ||
320 | GNUNET_BLOCK_TYPE_TEST, /* type */ | ||
321 | &d2->id.hashPubKey, /*key to search */ | ||
322 | 4U, /* replication level */ | ||
323 | GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | ||
324 | NULL, /* xquery */ | ||
325 | 0, /* xquery bits */ | ||
326 | &dht_get_id_handler, (void *)2); | ||
327 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " looking for %s\n", | ||
328 | GNUNET_h2s_full (&d_far->id.hashPubKey)); | ||
329 | get_h_far = GNUNET_DHT_get_start (hs[0], | ||
330 | GNUNET_BLOCK_TYPE_TEST, /* type */ | ||
331 | &d_far->id.hashPubKey, /*key to search */ | ||
332 | 4U, /* replication level */ | ||
333 | GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | ||
334 | NULL, /* xquery */ | ||
335 | 0, /* xquery bits */ | ||
336 | &dht_get_id_handler, (void *)3); | ||
337 | } | ||
338 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
339 | disconnect_task = | ||
340 | GNUNET_SCHEDULER_add_delayed (GET_TIMEOUT, &disconnect_peers, NULL); | ||
341 | } | ||
342 | |||
343 | /** | 195 | /** |
344 | * Task to put the id of each peer into the DHT. | 196 | * Task to put the id of each peer into the DHT. |
345 | * | 197 | * |
346 | * @param cls Closure (unused) | 198 | * @param cls array with NUM_PEERS DHT handles |
347 | * @param tc Task context | 199 | * @param tc Task context |
348 | * | ||
349 | */ | 200 | */ |
350 | static void | 201 | static void |
351 | put_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 202 | do_puts (void *cls, |
203 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
352 | { | 204 | { |
353 | struct GNUNET_TESTING_Daemon *d; | 205 | struct GNUNET_DHT_Handle **hs = cls; |
206 | struct GNUNET_HashCode key; | ||
207 | struct GNUNET_HashCode value; | ||
354 | unsigned int i; | 208 | unsigned int i; |
355 | 209 | ||
356 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "putting id's in DHT\n"); | 210 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
357 | for (i = 0; i < num_peers; i++) | 211 | "Putting values into DHT\n"); |
212 | for (i = 0; i < NUM_PEERS; i++) | ||
358 | { | 213 | { |
359 | d = GNUNET_TESTING_daemon_get (pg, i); | 214 | GNUNET_CRYPTO_hash (&i, sizeof (i), &key); |
360 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " putting into DHT: %s\n", | 215 | GNUNET_CRYPTO_hash (&key, sizeof (key), &value); |
361 | GNUNET_h2s_full (&d->id.hashPubKey)); | 216 | GNUNET_DHT_put (hs[i], &key, 10U, |
362 | GNUNET_DHT_put (hs[i], &d->id.hashPubKey, 10U, | ||
363 | GNUNET_DHT_RO_RECORD_ROUTE | | 217 | GNUNET_DHT_RO_RECORD_ROUTE | |
364 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | 218 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, |
365 | GNUNET_BLOCK_TYPE_TEST, sizeof (struct GNUNET_PeerIdentity), | 219 | GNUNET_BLOCK_TYPE_TEST, |
366 | (const char *) &d->id, GNUNET_TIME_UNIT_FOREVER_ABS, | 220 | sizeof (value), &value, |
367 | GNUNET_TIME_UNIT_FOREVER_REL, NULL, NULL); | 221 | GNUNET_TIME_UNIT_FOREVER_ABS, |
368 | 222 | GNUNET_TIME_UNIT_FOREVER_REL, | |
223 | NULL, NULL); | ||
369 | } | 224 | } |
370 | put_task = GNUNET_SCHEDULER_add_delayed (PUT_FREQUENCY, &put_id, NULL); | 225 | put_task = GNUNET_SCHEDULER_add_delayed (PUT_FREQUENCY, |
371 | if (GNUNET_SCHEDULER_NO_TASK == test_task) | 226 | &do_puts, hs); |
372 | test_task = GNUNET_SCHEDULER_add_now (&do_test, NULL); | ||
373 | } | 227 | } |
374 | 228 | ||
375 | 229 | ||
376 | /** | 230 | /** |
377 | * peergroup_ready: start test when all peers are connected | 231 | * Main function of the test. |
378 | * | ||
379 | * @param cls closure | ||
380 | * @param emsg error message | ||
381 | * | ||
382 | */ | ||
383 | static void | ||
384 | peergroup_ready (void *cls, const char *emsg) | ||
385 | { | ||
386 | struct GNUNET_TESTING_Daemon *d; | ||
387 | char *buf; | ||
388 | int buf_len; | ||
389 | unsigned int i; | ||
390 | |||
391 | if (emsg != NULL) | ||
392 | { | ||
393 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
394 | "Peergroup callback called with error, aborting test!\n"); | ||
395 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
396 | "Error from testing: `%s'\n", | ||
397 | emsg); | ||
398 | ok++; | ||
399 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
400 | return; | ||
401 | } | ||
402 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
403 | "Peer Group started successfully with %u connections\n", | ||
404 | total_connections); | ||
405 | if (data_file != NULL) | ||
406 | { | ||
407 | buf = NULL; | ||
408 | buf_len = GNUNET_asprintf (&buf, "CONNECTIONS_0: %u\n", total_connections); | ||
409 | if (buf_len > 0) | ||
410 | GNUNET_DISK_file_write (data_file, buf, buf_len); | ||
411 | GNUNET_free (buf); | ||
412 | } | ||
413 | peers_running = GNUNET_TESTING_daemons_running (pg); | ||
414 | |||
415 | GNUNET_assert (peers_running == num_peers); | ||
416 | hs = GNUNET_malloc (num_peers * sizeof (struct GNUNET_DHT_Handle *)); | ||
417 | for (i = 0; i < num_peers; i++) | ||
418 | { | ||
419 | d = GNUNET_TESTING_daemon_get (pg, i); | ||
420 | hs[i] = GNUNET_DHT_connect (d->cfg, 32); | ||
421 | } | ||
422 | |||
423 | test_task = GNUNET_SCHEDULER_NO_TASK; | ||
424 | put_task = GNUNET_SCHEDULER_add_now (&put_id, NULL); | ||
425 | disconnect_task = | ||
426 | GNUNET_SCHEDULER_add_delayed (GET_TIMEOUT, &disconnect_peers, NULL); | ||
427 | |||
428 | } | ||
429 | |||
430 | |||
431 | /** | ||
432 | * Function that will be called whenever two daemons are connected by | ||
433 | * the testing library. | ||
434 | * | 232 | * |
435 | * @param cls closure | 233 | * @param cls closure (NULL) |
436 | * @param first peer id for first daemon | 234 | * @param ctx argument to give to GNUNET_DHT_TEST_cleanup on test end |
437 | * @param second peer id for the second daemon | 235 | * @param num_peers number of peers that are running |
438 | * @param distance distance between the connected peers | 236 | * @param peers array of peers |
439 | * @param first_cfg config for the first daemon | 237 | * @param dhts handle to each of the DHTs of the peers |
440 | * @param second_cfg config for the second daemon | ||
441 | * @param first_daemon handle for the first daemon | ||
442 | * @param second_daemon handle for the second daemon | ||
443 | * @param emsg error message (NULL on success) | ||
444 | */ | ||
445 | static void | ||
446 | connect_cb (void *cls, const struct GNUNET_PeerIdentity *first, | ||
447 | const struct GNUNET_PeerIdentity *second, uint32_t distance, | ||
448 | const struct GNUNET_CONFIGURATION_Handle *first_cfg, | ||
449 | const struct GNUNET_CONFIGURATION_Handle *second_cfg, | ||
450 | struct GNUNET_TESTING_Daemon *first_daemon, | ||
451 | struct GNUNET_TESTING_Daemon *second_daemon, const char *emsg) | ||
452 | { | ||
453 | if (emsg == NULL) | ||
454 | { | ||
455 | total_connections++; | ||
456 | GNUNET_PEER_intern (first); | ||
457 | GNUNET_PEER_intern (second); | ||
458 | } | ||
459 | else | ||
460 | { | ||
461 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
462 | "Problem with new connection (%s)\n", emsg); | ||
463 | } | ||
464 | } | ||
465 | |||
466 | |||
467 | /** | ||
468 | * run: load configuration options and schedule test to run (start peergroup) | ||
469 | * @param cls closure | ||
470 | * @param args argv | ||
471 | * @param cfgfile configuration file name (can be NULL) | ||
472 | * @param cfg configuration handle | ||
473 | */ | 238 | */ |
474 | static void | 239 | static void |
475 | run (void *cls, char *const *args, const char *cfgfile, | 240 | run (void *cls, |
476 | const struct GNUNET_CONFIGURATION_Handle *cfg) | 241 | struct GNUNET_DHT_TEST_Context *ctx, |
242 | unsigned int num_peers, | ||
243 | struct GNUNET_TESTBED_Peer **peers, | ||
244 | struct GNUNET_DHT_Handle **dhts) | ||
477 | { | 245 | { |
478 | char *temp_str; | 246 | unsigned int i; |
479 | struct GNUNET_TESTING_Host *hosts; | 247 | unsigned int j; |
480 | char *data_filename; | 248 | struct GNUNET_HashCode key; |
481 | 249 | struct GetOperation *get_op; | |
482 | ok = 1; | 250 | |
483 | testing_cfg = GNUNET_CONFIGURATION_dup (cfg); | 251 | GNUNET_assert (NUM_PEERS == num_peers); |
484 | 252 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | |
485 | GNUNET_log_setup ("test_dht_topo", | 253 | "Peers setup, starting test\n"); |
486 | "WARNING", | 254 | /* FIXME: once testbed is finished, this call should |
487 | NULL); | 255 | no longer be needed */ |
488 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n"); | 256 | GNUNET_TESTBED_overlay_configure_topology (NULL, |
489 | GNUNET_CONFIGURATION_set_value_string (testing_cfg, "testing_old", | 257 | num_peers, |
490 | "use_progressbars", "YES"); | 258 | peers, |
491 | if (GNUNET_OK != | 259 | GNUNET_TESTBED_TOPOLOGY_LINE, |
492 | GNUNET_CONFIGURATION_get_value_number (testing_cfg, "testing_old", | 260 | GNUNET_TESTBED_TOPOLOGY_OPTION_END); |
493 | "num_peers", &num_peers)) | 261 | |
494 | { | 262 | put_task = GNUNET_SCHEDULER_add_now (&do_puts, dhts); |
495 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 263 | for (i=0;i<num_peers;i++) |
496 | "Option TESTING:NUM_PEERS is required!\n"); | ||
497 | return; | ||
498 | } | ||
499 | |||
500 | if (GNUNET_OK != | ||
501 | GNUNET_CONFIGURATION_get_value_string (testing_cfg, "testing_old", | ||
502 | "topology_output_file", | ||
503 | &topology_file)) | ||
504 | { | ||
505 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
506 | "Option test_dht_topo:topology_output_file is required!\n"); | ||
507 | return; | ||
508 | } | ||
509 | |||
510 | if (GNUNET_OK == | ||
511 | GNUNET_CONFIGURATION_get_value_string (testing_cfg, "test_dht_topo", | ||
512 | "data_output_file", | ||
513 | &data_filename)) | ||
514 | { | 264 | { |
515 | data_file = | 265 | GNUNET_CRYPTO_hash (&i, sizeof (i), &key); |
516 | GNUNET_DISK_file_open (data_filename, | 266 | for (j=0;j<num_peers;j++) |
517 | GNUNET_DISK_OPEN_READWRITE | | ||
518 | GNUNET_DISK_OPEN_CREATE, | ||
519 | GNUNET_DISK_PERM_USER_READ | | ||
520 | GNUNET_DISK_PERM_USER_WRITE); | ||
521 | if (data_file == NULL) | ||
522 | { | 267 | { |
523 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to open %s for output!\n", | 268 | get_op = GNUNET_malloc (sizeof (struct GetOperation)); |
524 | data_filename); | 269 | GNUNET_CONTAINER_DLL_insert (get_head, |
525 | GNUNET_free (data_filename); | 270 | get_tail, |
271 | get_op); | ||
272 | get_op->get = GNUNET_DHT_get_start (dhts[j], | ||
273 | GNUNET_BLOCK_TYPE_TEST, /* type */ | ||
274 | &key, /*key to search */ | ||
275 | 4U, /* replication level */ | ||
276 | GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | ||
277 | NULL, /* xquery */ | ||
278 | 0, /* xquery bits */ | ||
279 | &dht_get_handler, get_op); | ||
526 | } | 280 | } |
527 | } | 281 | } |
528 | 282 | timeout_task = GNUNET_SCHEDULER_add_delayed (GET_TIMEOUT, | |
529 | if (GNUNET_YES == | 283 | &shutdown_task, ctx); |
530 | GNUNET_CONFIGURATION_get_value_string (cfg, "test_dht_topo", | ||
531 | "output_file", &temp_str)) | ||
532 | { | ||
533 | output_file = | ||
534 | GNUNET_DISK_file_open (temp_str, | ||
535 | GNUNET_DISK_OPEN_READWRITE | | ||
536 | GNUNET_DISK_OPEN_CREATE, | ||
537 | GNUNET_DISK_PERM_USER_READ | | ||
538 | GNUNET_DISK_PERM_USER_WRITE); | ||
539 | if (output_file == NULL) | ||
540 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to open %s for output!\n", | ||
541 | temp_str); | ||
542 | } | ||
543 | GNUNET_free_non_null (temp_str); | ||
544 | |||
545 | hosts = GNUNET_TESTING_hosts_load (testing_cfg); | ||
546 | |||
547 | pg = GNUNET_TESTING_peergroup_start (testing_cfg, num_peers, TIMEOUT, | ||
548 | &connect_cb, &peergroup_ready, NULL, | ||
549 | hosts); | ||
550 | GNUNET_assert (pg != NULL); | ||
551 | shutdown_handle = | ||
552 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, | ||
553 | &shutdown_task, NULL); | ||
554 | } | 284 | } |
555 | 285 | ||
556 | 286 | ||
@@ -560,62 +290,28 @@ run (void *cls, char *const *args, const char *cfgfile, | |||
560 | int | 290 | int |
561 | main (int xargc, char *xargv[]) | 291 | main (int xargc, char *xargv[]) |
562 | { | 292 | { |
563 | static struct GNUNET_GETOPT_CommandLineOption options[] = { | 293 | const char *cfg_filename; |
564 | GNUNET_GETOPT_OPTION_END | 294 | const char *test_name; |
565 | }; | ||
566 | static char *const argv_torus[] = { "test-dht-2dtorus", | ||
567 | "-c", | ||
568 | "test_dht_2dtorus.conf", | ||
569 | NULL | ||
570 | }; | ||
571 | static char *const argv_line[] = { "test-dht-line", | ||
572 | "-c", | ||
573 | "test_dht_line.conf", | ||
574 | NULL | ||
575 | }; | ||
576 | char *const *argv; | ||
577 | int argc; | ||
578 | 295 | ||
579 | if (strstr (xargv[0], "test_dht_2dtorus") != NULL) | 296 | if (NULL != strstr (xargv[0], "test_dht_2dtorus")) |
580 | { | 297 | { |
581 | argv = argv_torus; | 298 | cfg_filename = "test_dht_2dtorus.conf"; |
582 | argc = sizeof (argv_torus) / sizeof (char *); | 299 | test_name = "test-dht-2dtorus"; |
583 | test_topology = TORUS; | ||
584 | } | 300 | } |
585 | else if (strstr (xargv[0], "test_dht_line") != NULL) | 301 | else if (NULL != strstr (xargv[0], "test_dht_line")) |
586 | { | 302 | { |
587 | argv = argv_line; | 303 | cfg_filename = "test_dht_line.conf"; |
588 | argc = sizeof (argv_line) / sizeof (char *); | 304 | test_name = "test-dht-line"; |
589 | test_topology = LINE; | ||
590 | } | 305 | } |
591 | else | 306 | else |
592 | { | 307 | { |
593 | GNUNET_break (0); | 308 | GNUNET_break (0); |
594 | return 1; | 309 | return 1; |
595 | } | 310 | } |
596 | GNUNET_PROGRAM_run (argc - 1, argv, | 311 | GNUNET_DHT_TEST_run (test_name, |
597 | xargv[0], | 312 | cfg_filename, |
598 | gettext_noop ("Test dht in different topologies."), | 313 | NUM_PEERS, |
599 | options, | 314 | &run, NULL); |
600 | &run, NULL); | ||
601 | #if REMOVE_DIR | ||
602 | GNUNET_DISK_directory_remove ("/tmp/test_dht_topo"); | ||
603 | #endif | ||
604 | if (0 == found_1) | ||
605 | { | ||
606 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "ID 1 not found!\n"); | ||
607 | } | ||
608 | if (TORUS == test_topology) | ||
609 | { | ||
610 | if (0 == found_2) | ||
611 | { | ||
612 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "ID 2 not found!\n"); | ||
613 | } | ||
614 | if (0 == found_far) | ||
615 | { | ||
616 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "ID far not found!\n"); | ||
617 | } | ||
618 | } | ||
619 | return ok; | 315 | return ok; |
620 | } | 316 | } |
621 | 317 | ||