diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-11-02 10:19:00 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-11-02 10:19:00 +0000 |
commit | c6ef80f13164795b0b53bc7c4c7cae2452cf861e (patch) | |
tree | 9205d3cf10cc02c359b229e291375ca483f93090 /src | |
parent | 2100eaeefbccd6cb2b6f952320092542f82a2051 (diff) | |
download | gnunet-c6ef80f13164795b0b53bc7c4c7cae2452cf861e.tar.gz gnunet-c6ef80f13164795b0b53bc7c4c7cae2452cf861e.zip |
-major DHT test cleanup
Diffstat (limited to 'src')
-rw-r--r-- | src/dht/Makefile.am | 73 | ||||
-rw-r--r-- | src/dht/dht.conf.in | 10 | ||||
-rw-r--r-- | src/dht/test_dht_2dtorus.conf | 67 | ||||
-rw-r--r-- | src/dht/test_dht_line.conf | 67 | ||||
-rw-r--r-- | src/dht/test_dht_monitor.c | 235 | ||||
-rw-r--r-- | src/dht/test_dht_multipeer.c | 859 | ||||
-rw-r--r-- | src/dht/test_dht_multipeer.conf (renamed from src/dht/test_dht_twopeer_data.conf) | 47 | ||||
-rw-r--r-- | src/dht/test_dht_multipeer_data.conf | 130 | ||||
-rw-r--r-- | src/dht/test_dht_multipeer_topology.dat (renamed from src/dht/multipeer_topo.dat) | 0 | ||||
-rw-r--r-- | src/dht/test_dht_topo.c | 160 | ||||
-rw-r--r-- | src/dht/test_dht_twopeer.c | 494 | ||||
-rw-r--r-- | src/dht/test_dht_twopeer_get_put.c | 590 | ||||
-rw-r--r-- | src/dht/test_dht_twopeer_path_tracking.c | 522 | ||||
-rw-r--r-- | src/dht/test_dht_twopeer_put_get.c | 510 |
14 files changed, 216 insertions, 3548 deletions
diff --git a/src/dht/Makefile.am b/src/dht/Makefile.am index 982c33815..0baf6b00e 100644 --- a/src/dht/Makefile.am +++ b/src/dht/Makefile.am | |||
@@ -123,27 +123,23 @@ libgnunetdhttest_a_DEPENDENCIES = \ | |||
123 | check_PROGRAMS = \ | 123 | check_PROGRAMS = \ |
124 | test_dht_api \ | 124 | test_dht_api \ |
125 | test_dht_twopeer \ | 125 | test_dht_twopeer \ |
126 | test_dht_twopeer_put_get \ | ||
127 | test_dht_twopeer_get_put \ | ||
128 | test_dht_twopeer_path_tracking \ | ||
129 | test_dht_multipeer \ | 126 | test_dht_multipeer \ |
130 | test_dht_line \ | 127 | test_dht_line \ |
131 | test_dht_2dtorus \ | 128 | test_dht_2dtorus |
132 | test_dht_monitor | 129 | # test_dht_monitor |
133 | 130 | ||
134 | if HAVE_EXPERIMENTAL | 131 | if HAVE_EXPERIMENTAL |
135 | NEW_TESTS = test_dht_line test_dht_2dtorus | 132 | # These tests still do not work as testbed does |
133 | # not support the respective topology op | ||
134 | NEW_TESTS = test_dht_2dtorus test_dht_multipeer | ||
136 | endif | 135 | endif |
137 | 136 | ||
138 | if ENABLE_TEST_RUN | 137 | if ENABLE_TEST_RUN |
139 | TESTS = test_dht_api $(check_SCRIPTS) \ | 138 | TESTS = test_dht_api $(check_SCRIPTS) \ |
140 | test_dht_twopeer \ | 139 | test_dht_twopeer \ |
141 | test_dht_twopeer_put_get \ | 140 | test_dht_line \ |
142 | test_dht_twopeer_get_put \ | 141 | $(NEW_TESTS) |
143 | test_dht_twopeer_path_tracking \ | 142 | # test_dht_monitor |
144 | test_dht_multipeer \ | ||
145 | $(NEW_TESTS) \ | ||
146 | test_dht_monitor | ||
147 | endif | 143 | endif |
148 | 144 | ||
149 | test_dht_api_SOURCES = \ | 145 | test_dht_api_SOURCES = \ |
@@ -156,9 +152,8 @@ test_dht_api_LDADD = \ | |||
156 | test_dht_api_DEPENDENCIES = \ | 152 | test_dht_api_DEPENDENCIES = \ |
157 | libgnunetdht.la | 153 | libgnunetdht.la |
158 | 154 | ||
159 | # twopeer is obsolete once new test_dht_topo works... | ||
160 | test_dht_twopeer_SOURCES = \ | 155 | test_dht_twopeer_SOURCES = \ |
161 | test_dht_twopeer.c | 156 | test_dht_topo.c |
162 | test_dht_twopeer_LDADD = \ | 157 | test_dht_twopeer_LDADD = \ |
163 | $(top_builddir)/src/util/libgnunetutil.la \ | 158 | $(top_builddir)/src/util/libgnunetutil.la \ |
164 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | 159 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ |
@@ -166,42 +161,6 @@ test_dht_twopeer_LDADD = \ | |||
166 | test_dht_twopeer_DEPENDENCIES = \ | 161 | test_dht_twopeer_DEPENDENCIES = \ |
167 | libgnunetdht.la | 162 | libgnunetdht.la |
168 | 163 | ||
169 | # twopeer_put_get is obsolete once new test_dht_topo works... | ||
170 | test_dht_twopeer_put_get_SOURCES = \ | ||
171 | test_dht_twopeer_put_get.c | ||
172 | test_dht_twopeer_put_get_LDADD = \ | ||
173 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
174 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
175 | $(top_builddir)/src/dht/libgnunetdht.la | ||
176 | |||
177 | # twopeer_get_put is obsolete once new test_dht_topo works... | ||
178 | test_dht_twopeer_get_put_SOURCES = \ | ||
179 | test_dht_twopeer_get_put.c | ||
180 | test_dht_twopeer_get_put_LDADD = \ | ||
181 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
182 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
183 | $(top_builddir)/src/dht/libgnunetdht.la | ||
184 | |||
185 | # twopeer_path_tracking is obsolete once new test_dht_topo works... | ||
186 | test_dht_twopeer_path_tracking_SOURCES = \ | ||
187 | test_dht_twopeer_path_tracking.c | ||
188 | test_dht_twopeer_path_tracking_LDADD = \ | ||
189 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
190 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
191 | $(top_builddir)/src/dht/libgnunetdht.la | ||
192 | |||
193 | # statistics functions should be integrated with test_dht_topo, | ||
194 | # then this one also becomes obsolete... | ||
195 | test_dht_multipeer_SOURCES = \ | ||
196 | test_dht_multipeer.c | ||
197 | test_dht_multipeer_LDADD = \ | ||
198 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
199 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
200 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
201 | $(top_builddir)/src/dht/libgnunetdht.la | ||
202 | test_dht_multipeer_DEPENDENCIES = \ | ||
203 | libgnunetdht.la | ||
204 | |||
205 | test_dht_2dtorus_SOURCES = \ | 164 | test_dht_2dtorus_SOURCES = \ |
206 | test_dht_topo.c | 165 | test_dht_topo.c |
207 | test_dht_2dtorus_LDADD = \ | 166 | test_dht_2dtorus_LDADD = \ |
@@ -222,6 +181,16 @@ test_dht_line_LDADD = \ | |||
222 | test_dht_line_DEPENDENCIES = \ | 181 | test_dht_line_DEPENDENCIES = \ |
223 | libgnunetdht.la | 182 | libgnunetdht.la |
224 | 183 | ||
184 | test_dht_multipeer_SOURCES = \ | ||
185 | test_dht_topo.c | ||
186 | test_dht_multipeer_LDADD = \ | ||
187 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
188 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
189 | $(top_builddir)/src/testing_old/libgnunettesting_old.la \ | ||
190 | $(top_builddir)/src/dht/libgnunetdht.la | ||
191 | test_dht_multipeer_DEPENDENCIES = \ | ||
192 | libgnunetdht.la | ||
193 | |||
225 | # fixme, rewrite based on test_dht_topo.c! | 194 | # fixme, rewrite based on test_dht_topo.c! |
226 | test_dht_monitor_SOURCES = test_dht_monitor.c | 195 | test_dht_monitor_SOURCES = test_dht_monitor.c |
227 | test_dht_monitor_LDADD = \ | 196 | test_dht_monitor_LDADD = \ |
@@ -236,11 +205,11 @@ EXTRA_DIST = \ | |||
236 | test_dht_api_data.conf \ | 205 | test_dht_api_data.conf \ |
237 | test_dht_api_peer1.conf \ | 206 | test_dht_api_peer1.conf \ |
238 | test_dht_twopeer_data.conf \ | 207 | test_dht_twopeer_data.conf \ |
239 | test_dht_multipeer_data.conf \ | 208 | test_dht_multipeer.conf \ |
240 | test_dht_2dtorus.conf \ | 209 | test_dht_2dtorus.conf \ |
241 | test_dht_line.conf \ | 210 | test_dht_line.conf \ |
242 | test_dht_tools.py.in \ | 211 | test_dht_tools.py.in \ |
243 | multipeer_topo.dat | 212 | test_dht_multipeer_topology.dat |
244 | 213 | ||
245 | check_SCRIPTS = \ | 214 | check_SCRIPTS = \ |
246 | test_dht_tools.py | 215 | test_dht_tools.py |
diff --git a/src/dht/dht.conf.in b/src/dht/dht.conf.in index bcc0192ab..553429dc8 100644 --- a/src/dht/dht.conf.in +++ b/src/dht/dht.conf.in | |||
@@ -21,15 +21,7 @@ UNIX_MATCH_GID = YES | |||
21 | # REJECT_FROM = | 21 | # REJECT_FROM = |
22 | # REJECT_FROM6 = | 22 | # REJECT_FROM6 = |
23 | # PREFIX = | 23 | # PREFIX = |
24 | # DO_FIND_PEER = | 24 | |
25 | # STRICT_KADEMLIA = | ||
26 | # USE_MAX_HOPS = | ||
27 | # MAX_HOPS = | ||
28 | # REPUBLISH = YES | ||
29 | # REPLICATION_FREQUENCY = 60 | ||
30 | # STOP_ON_CLOSEST = | ||
31 | # STOP_FOUND = | ||
32 | # CONVERGE_MODIFIER = | ||
33 | 25 | ||
34 | # Special option to disable DHT calling 'try_connect' (for testing) | 26 | # Special option to disable DHT calling 'try_connect' (for testing) |
35 | DISABLE_TRY_CONNECT = NO | 27 | DISABLE_TRY_CONNECT = NO |
diff --git a/src/dht/test_dht_2dtorus.conf b/src/dht/test_dht_2dtorus.conf index fa8c25011..29188cbe4 100644 --- a/src/dht/test_dht_2dtorus.conf +++ b/src/dht/test_dht_2dtorus.conf | |||
@@ -1,34 +1,15 @@ | |||
1 | [PATHS] | 1 | [PATHS] |
2 | SERVICEHOME = /tmp/test_dht_topo/ | 2 | SERVICEHOME = /tmp/test_dht_2dtorus/ |
3 | 3 | ||
4 | [arm] | 4 | [arm] |
5 | PORT = 10010 | ||
6 | DEFAULTSERVICES = core dht | 5 | DEFAULTSERVICES = core dht |
7 | #DEBUG = YES | ||
8 | |||
9 | [statistics] | ||
10 | AUTOSTART = YES | ||
11 | PORT = 10000 | ||
12 | |||
13 | [dht] | ||
14 | DEBUG = NO | ||
15 | AUTOSTART = YES | ||
16 | ACCEPT_FROM6 = ::1; | ||
17 | ACCEPT_FROM = 127.0.0.1; | ||
18 | HOSTNAME = localhost | ||
19 | PORT = 10001 | ||
20 | 6 | ||
21 | [dns] | 7 | [dns] |
22 | AUTOSTART = NO | 8 | AUTOSTART = NO |
23 | PORT = 10011 | ||
24 | |||
25 | [transport] | ||
26 | PORT = 10002 | ||
27 | AUTOSTART = YES | ||
28 | 9 | ||
29 | [nat] | 10 | [nat] |
30 | DISABLEV6 = YES | 11 | DISABLEV6 = YES |
31 | BINDTO = 127.0.0.1 | 12 | RETURN_LOCAL_ADDRESSES = YES |
32 | ENABLE_UPNP = NO | 13 | ENABLE_UPNP = NO |
33 | BEHIND_NAT = NO | 14 | BEHIND_NAT = NO |
34 | ALLOW_NAT = NO | 15 | ALLOW_NAT = NO |
@@ -39,54 +20,18 @@ EXTERNAL_ADDRESS = 127.0.0.1 | |||
39 | WAN_QUOTA_IN = 1 GB | 20 | WAN_QUOTA_IN = 1 GB |
40 | WAN_QUOTA_OUT = 1 GB | 21 | WAN_QUOTA_OUT = 1 GB |
41 | 22 | ||
42 | [core] | ||
43 | AUTOSTART = YES | ||
44 | PORT = 10003 | ||
45 | |||
46 | [peerinfo] | ||
47 | AUTOSTART = YES | ||
48 | PORT = 10004 | ||
49 | |||
50 | [testing] | 23 | [testing] |
51 | WEAKRANDOM = YES | 24 | WEAKRANDOM = YES |
52 | 25 | ||
53 | [testing_old] | 26 | [testbed] |
54 | NUM_PEERS = 16 | 27 | OVERLAY_TOPOLOGY = 2D_TORUS |
55 | TOPOLOGY = NONE | ||
56 | CONNECT_TOPOLOGY = 2D_TORUS | ||
57 | BLACKLIST_TOPOLOGY = 2D_TORUS | ||
58 | #TOPOLOGY_FILE = small.dat | ||
59 | #CONNECT_TOPOLOGY = ERDOS_RENYI | ||
60 | #CONNECT_TOPOLOGY_OPTION = CONNECT_MINIMUM | ||
61 | #CONNECT_TOPOLOGY_OPTION_MODIFIER = 25 | ||
62 | #PERCENTAGE = 3 | ||
63 | #PROBABILITY = .1 | ||
64 | F2F = NO | ||
65 | CONNECT_TIMEOUT = 60 s | ||
66 | CONNECT_ATTEMPTS = 3 | ||
67 | DEBUG = YES | ||
68 | HOSTKEYSFILE = ${DATADIR}/testing_hostkeys.dat | ||
69 | MAX_CONCURRENT_SSH = 20 | ||
70 | USE_PROGRESSBARS = YES | ||
71 | PEERGROUP_TIMEOUT = 2400 s | ||
72 | TOPOLOGY_OUTPUT_FILE = 2dtorus_topo_initial | ||
73 | MAX_OUTSTANDING_CONNECTIONS = 75 | ||
74 | #SINGLE_PEERINFO_PER_HOST = YES | ||
75 | #NUM_PEERINFO_PER_HOST = 10 | ||
76 | #SINGLE_STATISTICS_PER_HOST = YES | ||
77 | #NUM_STATISTICS_PER_HOST = 10 | ||
78 | DELETE_FILES = YES | ||
79 | |||
80 | [test_dht_topo] | ||
81 | CONNECTION_LIMIT = 20 | ||
82 | #DATA_OUTPUT_FILE=data_output | ||
83 | |||
84 | 28 | ||
85 | [nse] | 29 | [nse] |
86 | WORKDELAY = 500 ms | 30 | WORKDELAY = 500 ms |
87 | INTERVAL = 60 s | 31 | INTERVAL = 60 s |
88 | WORKBITS = 0 | 32 | WORKBITS = 0 |
33 | |||
89 | [vpn] | 34 | [vpn] |
90 | AUTOSTART=NO | 35 | AUTOSTART = NO |
91 | 36 | ||
92 | 37 | ||
diff --git a/src/dht/test_dht_line.conf b/src/dht/test_dht_line.conf index 12c682d2d..e2bb54f1b 100644 --- a/src/dht/test_dht_line.conf +++ b/src/dht/test_dht_line.conf | |||
@@ -1,34 +1,15 @@ | |||
1 | [PATHS] | 1 | [PATHS] |
2 | SERVICEHOME = /tmp/test_dht_topo/ | 2 | SERVICEHOME = /tmp/test_dht_line/ |
3 | 3 | ||
4 | [arm] | 4 | [arm] |
5 | PORT = 10010 | ||
6 | DEFAULTSERVICES = core dht | 5 | DEFAULTSERVICES = core dht |
7 | #DEBUG = YES | ||
8 | |||
9 | [statistics] | ||
10 | AUTOSTART = YES | ||
11 | PORT = 10000 | ||
12 | |||
13 | [dht] | ||
14 | DEBUG = NO | ||
15 | AUTOSTART = YES | ||
16 | ACCEPT_FROM6 = ::1; | ||
17 | ACCEPT_FROM = 127.0.0.1; | ||
18 | HOSTNAME = localhost | ||
19 | PORT = 10001 | ||
20 | 6 | ||
21 | [dns] | 7 | [dns] |
22 | AUTOSTART = NO | 8 | AUTOSTART = NO |
23 | PORT = 10011 | ||
24 | |||
25 | [transport] | ||
26 | PORT = 10002 | ||
27 | AUTOSTART = YES | ||
28 | 9 | ||
29 | [nat] | 10 | [nat] |
30 | DISABLEV6 = YES | 11 | DISABLEV6 = YES |
31 | BINDTO = 127.0.0.1 | 12 | RETURN_LOCAL_ADDRESSES = YES |
32 | ENABLE_UPNP = NO | 13 | ENABLE_UPNP = NO |
33 | BEHIND_NAT = NO | 14 | BEHIND_NAT = NO |
34 | ALLOW_NAT = NO | 15 | ALLOW_NAT = NO |
@@ -39,48 +20,11 @@ EXTERNAL_ADDRESS = 127.0.0.1 | |||
39 | WAN_QUOTA_IN = 1 GB | 20 | WAN_QUOTA_IN = 1 GB |
40 | WAN_QUOTA_OUT = 1 GB | 21 | WAN_QUOTA_OUT = 1 GB |
41 | 22 | ||
42 | [core] | ||
43 | AUTOSTART = YES | ||
44 | PORT = 10003 | ||
45 | |||
46 | [peerinfo] | ||
47 | AUTOSTART = YES | ||
48 | PORT = 10004 | ||
49 | |||
50 | [testing] | 23 | [testing] |
51 | WEAKRANDOM = YES | 24 | WEAKRANDOM = YES |
52 | 25 | ||
53 | [testing_old] | 26 | [testbed] |
54 | NUM_PEERS = 5 | 27 | OVERLAY_TOPOLOGY = LINE |
55 | TOPOLOGY = NONE | ||
56 | CONNECT_TOPOLOGY = LINE | ||
57 | BLACKLIST_TOPOLOGY = LINE | ||
58 | BLACKLIST_TRANSPORTS = tcp udp http unix | ||
59 | #TOPOLOGY_FILE = small.dat | ||
60 | #CONNECT_TOPOLOGY = ERDOS_RENYI | ||
61 | #CONNECT_TOPOLOGY_OPTION = CONNECT_MINIMUM | ||
62 | #CONNECT_TOPOLOGY_OPTION_MODIFIER = 25 | ||
63 | #PERCENTAGE = 3 | ||
64 | #PROBABILITY = .1 | ||
65 | F2F = NO | ||
66 | CONNECT_TIMEOUT = 60 s | ||
67 | CONNECT_ATTEMPTS = 3 | ||
68 | DEBUG = YES | ||
69 | HOSTKEYSFILE = ${DATADIR}/testing_hostkeys.dat | ||
70 | MAX_CONCURRENT_SSH = 10 | ||
71 | USE_PROGRESSBARS = YES | ||
72 | PEERGROUP_TIMEOUT = 2400 s | ||
73 | TOPOLOGY_OUTPUT_FILE = line_topo_initial | ||
74 | MAX_OUTSTANDING_CONNECTIONS = 75 | ||
75 | #SINGLE_PEERINFO_PER_HOST = YES | ||
76 | #NUM_PEERINFO_PER_HOST = 10 | ||
77 | #SINGLE_STATISTICS_PER_HOST = YES | ||
78 | #NUM_STATISTICS_PER_HOST = 10 | ||
79 | DELETE_FILES = YES | ||
80 | |||
81 | [test_dht_topo] | ||
82 | CONNECTION_LIMIT = 5 | ||
83 | #DATA_OUTPUT_FILE=data_output | ||
84 | 28 | ||
85 | [namestore] | 29 | [namestore] |
86 | AUTOSTART = NO | 30 | AUTOSTART = NO |
@@ -89,7 +33,8 @@ AUTOSTART = NO | |||
89 | WORKDELAY = 500 ms | 33 | WORKDELAY = 500 ms |
90 | INTERVAL = 60 s | 34 | INTERVAL = 60 s |
91 | WORKBITS = 0 | 35 | WORKBITS = 0 |
36 | |||
92 | [vpn] | 37 | [vpn] |
93 | AUTOSTART=NO | 38 | AUTOSTART = NO |
94 | 39 | ||
95 | 40 | ||
diff --git a/src/dht/test_dht_monitor.c b/src/dht/test_dht_monitor.c index f6474a37e..e8be7e49c 100644 --- a/src/dht/test_dht_monitor.c +++ b/src/dht/test_dht_monitor.c | |||
@@ -426,71 +426,38 @@ monitor_res_cb (void *cls, | |||
426 | 426 | ||
427 | 427 | ||
428 | /** | 428 | /** |
429 | * peergroup_ready: start test when all peers are connected | 429 | * Main function of the test. |
430 | * | 430 | * |
431 | * @param cls closure | 431 | * @param cls closure (NULL) |
432 | * @param emsg error message | 432 | * @param ctx argument to give to GNUNET_DHT_TEST_cleanup on test end |
433 | * @param num_peers number of peers that are running | ||
434 | * @param peers array of peers | ||
435 | * @param dhts handle to each of the DHTs of the peers | ||
433 | */ | 436 | */ |
434 | static void | 437 | static void |
435 | peergroup_ready (void *cls, const char *emsg) | 438 | run (void *cls, |
439 | struct GNUNET_DHT_TEST_Context *ctx, | ||
440 | unsigned int num_peers, | ||
441 | struct GNUNET_TESTBED_Peer **peers, | ||
442 | struct GNUNET_DHT_Handle **dhts) | ||
436 | { | 443 | { |
437 | struct GNUNET_TESTING_Daemon *d; | ||
438 | char *buf; | ||
439 | int buf_len; | ||
440 | unsigned int i; | 444 | unsigned int i; |
441 | 445 | ||
442 | if (emsg != NULL) | 446 | GNUNET_assert (NUM_PEERS == num_peers); |
443 | { | 447 | my_peers = peers; |
444 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
445 | "test: Peergroup callback called with error, aborting test!\n"); | ||
446 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Error from testing: `%s'\n", | ||
447 | emsg); | ||
448 | ok++; | ||
449 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
450 | return; | ||
451 | } | ||
452 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
453 | "test: Peer Group started successfully with %u connections\n", | ||
454 | total_connections); | ||
455 | if (data_file != NULL) | ||
456 | { | ||
457 | buf = NULL; | ||
458 | buf_len = GNUNET_asprintf (&buf, "CONNECTIONS_0: %u\n", total_connections); | ||
459 | if (buf_len > 0) | ||
460 | GNUNET_DISK_file_write (data_file, buf, buf_len); | ||
461 | GNUNET_free (buf); | ||
462 | } | ||
463 | peers_running = GNUNET_TESTING_daemons_running (pg); | ||
464 | |||
465 | GNUNET_assert (peers_running == num_peers); | ||
466 | hs = GNUNET_malloc (num_peers * sizeof (struct GNUNET_DHT_Handle *)); | ||
467 | mhs = GNUNET_malloc (num_peers * sizeof (struct GNUNET_DHT_MonitorHandle *)); | 448 | mhs = GNUNET_malloc (num_peers * sizeof (struct GNUNET_DHT_MonitorHandle *)); |
468 | d_far = o = NULL; | ||
469 | o = GNUNET_TESTING_daemon_get (pg, 0); | ||
470 | d_far = GNUNET_TESTING_daemon_get (pg, 4); | ||
471 | |||
472 | for (i = 0; i < num_peers; i++) | 449 | for (i = 0; i < num_peers; i++) |
473 | { | 450 | { |
474 | d = GNUNET_TESTING_daemon_get (pg, i); | 451 | d = GNUNET_TESTING_daemon_get (pg, i); |
475 | hs[i] = GNUNET_DHT_connect (d->cfg, 32); | 452 | hs[i] = GNUNET_DHT_connect (d->cfg, 32); |
476 | mhs[i] = GNUNET_DHT_monitor_start(hs[i], | 453 | mhs[i] = GNUNET_DHT_monitor_start (hs[i], |
477 | GNUNET_BLOCK_TYPE_ANY, | 454 | GNUNET_BLOCK_TYPE_ANY, |
478 | NULL, | 455 | NULL, |
479 | &monitor_get_cb, | 456 | &monitor_get_cb, |
480 | &monitor_res_cb, | 457 | &monitor_res_cb, |
481 | &monitor_put_cb, | 458 | &monitor_put_cb, |
482 | (void *)(long)i); | 459 | (void *)(long)i); |
483 | } | 460 | } |
484 | |||
485 | if ((NULL == o) || (NULL == d_far)) | ||
486 | { | ||
487 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
488 | "test: Error getting daemons from pg\n"); | ||
489 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
490 | disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_peers, NULL); | ||
491 | return; | ||
492 | } | ||
493 | monitor_counter = 0; | ||
494 | put_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | 461 | put_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply |
495 | (GNUNET_TIME_UNIT_SECONDS, 3), | 462 | (GNUNET_TIME_UNIT_SECONDS, 3), |
496 | &put_id, NULL); | 463 | &put_id, NULL); |
@@ -500,173 +467,21 @@ peergroup_ready (void *cls, const char *emsg) | |||
500 | NULL); | 467 | NULL); |
501 | disconnect_task = | 468 | disconnect_task = |
502 | GNUNET_SCHEDULER_add_delayed (GET_TIMEOUT, &disconnect_peers, NULL); | 469 | GNUNET_SCHEDULER_add_delayed (GET_TIMEOUT, &disconnect_peers, NULL); |
503 | |||
504 | } | ||
505 | |||
506 | |||
507 | /** | ||
508 | * Function that will be called whenever two daemons are connected by | ||
509 | * the testing library. | ||
510 | * | ||
511 | * @param cls closure | ||
512 | * @param first peer id for first daemon | ||
513 | * @param second peer id for the second daemon | ||
514 | * @param distance distance between the connected peers | ||
515 | * @param first_cfg config for the first daemon | ||
516 | * @param second_cfg config for the second daemon | ||
517 | * @param first_daemon handle for the first daemon | ||
518 | * @param second_daemon handle for the second daemon | ||
519 | * @param emsg error message (NULL on success) | ||
520 | */ | ||
521 | static void | ||
522 | connect_cb (void *cls, const struct GNUNET_PeerIdentity *first, | ||
523 | const struct GNUNET_PeerIdentity *second, uint32_t distance, | ||
524 | const struct GNUNET_CONFIGURATION_Handle *first_cfg, | ||
525 | const struct GNUNET_CONFIGURATION_Handle *second_cfg, | ||
526 | struct GNUNET_TESTING_Daemon *first_daemon, | ||
527 | struct GNUNET_TESTING_Daemon *second_daemon, const char *emsg) | ||
528 | { | ||
529 | |||
530 | if (emsg == NULL) | ||
531 | { | ||
532 | total_connections++; | ||
533 | GNUNET_PEER_intern (first); | ||
534 | GNUNET_PEER_intern (second); | ||
535 | } | ||
536 | else | ||
537 | { | ||
538 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
539 | "test: Problem with new connection (%s)\n", emsg); | ||
540 | } | ||
541 | } | 470 | } |
542 | 471 | ||
543 | 472 | ||
544 | /** | 473 | /** |
545 | * run: load configuration options and schedule test to run (start peergroup) | ||
546 | * @param cls closure | ||
547 | * @param args argv | ||
548 | * @param cfgfile configuration file name (can be NULL) | ||
549 | * @param cfg configuration handle | ||
550 | */ | ||
551 | static void | ||
552 | run (void *cls, char *const *args, const char *cfgfile, | ||
553 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
554 | { | ||
555 | char *temp_str; | ||
556 | struct GNUNET_TESTING_Host *hosts; | ||
557 | char *data_filename; | ||
558 | |||
559 | ok = 1; | ||
560 | testing_cfg = GNUNET_CONFIGURATION_dup (cfg); | ||
561 | |||
562 | GNUNET_log_setup ("test_dht_monitor", | ||
563 | "WARNING", | ||
564 | NULL); | ||
565 | |||
566 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Starting daemons.\n"); | ||
567 | GNUNET_CONFIGURATION_set_value_string (testing_cfg, "testing_old", | ||
568 | "use_progressbars", "YES"); | ||
569 | if (GNUNET_OK != | ||
570 | GNUNET_CONFIGURATION_get_value_number (testing_cfg, "testing_old", | ||
571 | "num_peers", &num_peers)) | ||
572 | { | ||
573 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
574 | "Option TESTING:NUM_PEERS is required!\n"); | ||
575 | return; | ||
576 | } | ||
577 | |||
578 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (testing_cfg, "testing_old", | ||
579 | "topology_output_file", | ||
580 | &topology_file)) | ||
581 | { | ||
582 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
583 | "Option test_dht_monitor:topology_output_file is required!\n"); | ||
584 | return; | ||
585 | } | ||
586 | |||
587 | if (GNUNET_OK == | ||
588 | GNUNET_CONFIGURATION_get_value_string (testing_cfg, "test_dht_topo", | ||
589 | "data_output_file", | ||
590 | &data_filename)) | ||
591 | { | ||
592 | data_file = | ||
593 | GNUNET_DISK_file_open (data_filename, | ||
594 | GNUNET_DISK_OPEN_READWRITE | | ||
595 | GNUNET_DISK_OPEN_CREATE, | ||
596 | GNUNET_DISK_PERM_USER_READ | | ||
597 | GNUNET_DISK_PERM_USER_WRITE); | ||
598 | if (data_file == NULL) | ||
599 | { | ||
600 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to open %s for output!\n", | ||
601 | data_filename); | ||
602 | GNUNET_free (data_filename); | ||
603 | } | ||
604 | } | ||
605 | |||
606 | if (GNUNET_YES == | ||
607 | GNUNET_CONFIGURATION_get_value_string (cfg, "test_dht_topo", | ||
608 | "output_file", &temp_str)) | ||
609 | { | ||
610 | output_file = | ||
611 | GNUNET_DISK_file_open (temp_str, | ||
612 | GNUNET_DISK_OPEN_READWRITE | | ||
613 | GNUNET_DISK_OPEN_CREATE, | ||
614 | GNUNET_DISK_PERM_USER_READ | | ||
615 | GNUNET_DISK_PERM_USER_WRITE); | ||
616 | if (output_file == NULL) | ||
617 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to open %s for output!\n", | ||
618 | temp_str); | ||
619 | } | ||
620 | GNUNET_free_non_null (temp_str); | ||
621 | |||
622 | hosts = GNUNET_TESTING_hosts_load (testing_cfg); | ||
623 | |||
624 | pg = GNUNET_TESTING_peergroup_start (testing_cfg, num_peers, TIMEOUT, | ||
625 | &connect_cb, &peergroup_ready, NULL, | ||
626 | hosts); | ||
627 | GNUNET_assert (pg != NULL); | ||
628 | shutdown_handle = | ||
629 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, | ||
630 | &shutdown_task, NULL); | ||
631 | } | ||
632 | |||
633 | |||
634 | /** | ||
635 | * test_dht_monitor command line options | ||
636 | */ | ||
637 | static struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
638 | {'V', "verbose", NULL, | ||
639 | gettext_noop ("be verbose (print progress information)"), | ||
640 | 0, &GNUNET_GETOPT_set_one, &verbose}, | ||
641 | GNUNET_GETOPT_OPTION_END | ||
642 | }; | ||
643 | |||
644 | |||
645 | /** | ||
646 | * Main: start test | 474 | * Main: start test |
647 | */ | 475 | */ |
648 | int | 476 | int |
649 | main (int xargc, char *xargv[]) | 477 | main (int xargc, char *xargv[]) |
650 | { | 478 | { |
651 | char *const argv[] = { "test-dht-monitor", | 479 | GNUNET_DHT_TEST_run ("test-dht-monitor", |
652 | "-c", | 480 | "test_dht_monitor.conf", |
653 | "test_dht_line.conf", | 481 | NUM_PEERS, |
654 | NULL | 482 | &run, NULL); |
655 | }; | ||
656 | |||
657 | in_test = GNUNET_NO; | ||
658 | GNUNET_PROGRAM_run (sizeof (argv) / sizeof (char *) - 1, argv, | ||
659 | "test_dht_monitor", | ||
660 | gettext_noop ("Test dht monitoring in a line."), | ||
661 | options, &run, NULL); | ||
662 | #if REMOVE_DIR | ||
663 | GNUNET_DISK_directory_remove ("/tmp/test_dht_monitor"); | ||
664 | #endif | ||
665 | if (0 != ok) | ||
666 | { | ||
667 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: FAILED!\n"); | ||
668 | } | ||
669 | return ok; | 483 | return ok; |
670 | } | 484 | } |
671 | 485 | ||
486 | |||
672 | /* end of test_dht_monitor.c */ | 487 | /* end of test_dht_monitor.c */ |
diff --git a/src/dht/test_dht_multipeer.c b/src/dht/test_dht_multipeer.c deleted file mode 100644 index 656b4ac06..000000000 --- a/src/dht/test_dht_multipeer.c +++ /dev/null | |||
@@ -1,859 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009 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 | * @file dht/test_dht_multipeer.c | ||
22 | * @brief testcase for testing DHT service with | ||
23 | * multiple peers. | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_testing_lib.h" | ||
27 | #include "gnunet_core_service.h" | ||
28 | #include "gnunet_dht_service.h" | ||
29 | |||
30 | /* Timeout for entire testcase */ | ||
31 | #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 30) | ||
32 | |||
33 | /* Timeout for waiting for replies to get requests */ | ||
34 | #define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 300) | ||
35 | |||
36 | /* */ | ||
37 | #define START_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30) | ||
38 | |||
39 | /* Timeout for waiting for gets to complete */ | ||
40 | #define GET_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 50) | ||
41 | |||
42 | /* Timeout for waiting for puts to complete */ | ||
43 | #define PUT_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 50) | ||
44 | |||
45 | /* If number of peers not in config file, use this number */ | ||
46 | #define DEFAULT_NUM_PEERS 10 | ||
47 | |||
48 | #define TEST_DATA_SIZE 8 | ||
49 | |||
50 | #define MAX_OUTSTANDING_PUTS 100 | ||
51 | |||
52 | #define MAX_OUTSTANDING_GETS 100 | ||
53 | |||
54 | #define PATH_TRACKING GNUNET_NO | ||
55 | |||
56 | |||
57 | |||
58 | struct TestPutContext | ||
59 | { | ||
60 | /** | ||
61 | * This is a linked list | ||
62 | */ | ||
63 | struct TestPutContext *next; | ||
64 | |||
65 | /** | ||
66 | * This is a linked list | ||
67 | */ | ||
68 | struct TestPutContext *prev; | ||
69 | |||
70 | /** | ||
71 | * Handle to the first peers DHT service (via the API) | ||
72 | */ | ||
73 | struct GNUNET_DHT_Handle *dht_handle; | ||
74 | |||
75 | /** | ||
76 | * Handle to the PUT peer daemon | ||
77 | */ | ||
78 | struct GNUNET_TESTING_Daemon *daemon; | ||
79 | |||
80 | /** | ||
81 | * Identifier for this PUT | ||
82 | */ | ||
83 | uint32_t uid; | ||
84 | |||
85 | /** | ||
86 | * Task handle for processing of the put. | ||
87 | */ | ||
88 | GNUNET_SCHEDULER_TaskIdentifier task; | ||
89 | }; | ||
90 | |||
91 | |||
92 | struct TestGetContext | ||
93 | { | ||
94 | /** | ||
95 | * This is a linked list | ||
96 | */ | ||
97 | struct TestGetContext *next; | ||
98 | |||
99 | /** | ||
100 | * This is a linked list | ||
101 | */ | ||
102 | struct TestGetContext *prev; | ||
103 | |||
104 | /** | ||
105 | * Handle to the first peers DHT service (via the API) | ||
106 | */ | ||
107 | struct GNUNET_DHT_Handle *dht_handle; | ||
108 | |||
109 | /** | ||
110 | * Handle for the DHT get request | ||
111 | */ | ||
112 | struct GNUNET_DHT_GetHandle *get_handle; | ||
113 | |||
114 | /** | ||
115 | * Handle to the GET peer daemon | ||
116 | */ | ||
117 | struct GNUNET_TESTING_Daemon *daemon; | ||
118 | |||
119 | /** | ||
120 | * Identifier for this GET | ||
121 | */ | ||
122 | uint32_t uid; | ||
123 | |||
124 | /** | ||
125 | * Task for disconnecting DHT handles (and stopping GET) | ||
126 | */ | ||
127 | GNUNET_SCHEDULER_TaskIdentifier task; | ||
128 | |||
129 | /** | ||
130 | * Whether or not this request has been fulfilled already. | ||
131 | */ | ||
132 | int succeeded; | ||
133 | }; | ||
134 | |||
135 | |||
136 | /** | ||
137 | * List of GETS to perform | ||
138 | */ | ||
139 | static struct TestGetContext *all_gets_head; | ||
140 | |||
141 | /** | ||
142 | * List of GETS to perform | ||
143 | */ | ||
144 | static struct TestGetContext *all_gets_tail; | ||
145 | |||
146 | /** | ||
147 | * List of PUTS to perform | ||
148 | */ | ||
149 | static struct TestPutContext *all_puts_head; | ||
150 | |||
151 | /** | ||
152 | * List of PUTS to perform | ||
153 | */ | ||
154 | static struct TestPutContext *all_puts_tail; | ||
155 | |||
156 | /** | ||
157 | * Handle to the set of all peers run for this test. | ||
158 | */ | ||
159 | static struct GNUNET_TESTING_PeerGroup *pg; | ||
160 | |||
161 | /** | ||
162 | * Total number of peers to run, set based on config file. | ||
163 | */ | ||
164 | static unsigned long long num_peers; | ||
165 | |||
166 | /** | ||
167 | * How many puts do we currently have in flight? | ||
168 | */ | ||
169 | static unsigned long long outstanding_puts; | ||
170 | |||
171 | /** | ||
172 | * How many puts are done? | ||
173 | */ | ||
174 | static unsigned long long puts_completed; | ||
175 | |||
176 | /** | ||
177 | * How many puts do we currently have in flight? | ||
178 | */ | ||
179 | static unsigned long long outstanding_gets; | ||
180 | |||
181 | /** | ||
182 | * How many gets are done? | ||
183 | */ | ||
184 | static unsigned long long gets_completed; | ||
185 | |||
186 | /** | ||
187 | * How many gets failed? | ||
188 | */ | ||
189 | static unsigned long long gets_failed; | ||
190 | |||
191 | /** | ||
192 | * Directory to remove on shutdown. | ||
193 | */ | ||
194 | static char *test_directory; | ||
195 | |||
196 | /** | ||
197 | * Option to use when routing. | ||
198 | */ | ||
199 | static enum GNUNET_DHT_RouteOption route_option; | ||
200 | |||
201 | /** | ||
202 | * Task handle to use to schedule test failure / success. | ||
203 | */ | ||
204 | static GNUNET_SCHEDULER_TaskIdentifier die_task; | ||
205 | |||
206 | /** | ||
207 | * Task handle to use to schedule test shutdown | ||
208 | */ | ||
209 | GNUNET_SCHEDULER_TaskIdentifier shutdown_task; | ||
210 | |||
211 | /** | ||
212 | * Global return value (0 for success, anything else for failure) | ||
213 | */ | ||
214 | static int ok; | ||
215 | |||
216 | |||
217 | /** | ||
218 | * Check whether peers successfully shut down. | ||
219 | */ | ||
220 | static void | ||
221 | shutdown_callback (void *cls, const char *emsg) | ||
222 | { | ||
223 | if (emsg != NULL) | ||
224 | { | ||
225 | FPRINTF (stderr, "Failed to shutdown testing topology: %s\n", emsg); | ||
226 | if (ok == 0) | ||
227 | ok = 2; | ||
228 | } | ||
229 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown callback completed.\n"); | ||
230 | } | ||
231 | |||
232 | static void | ||
233 | do_stop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
234 | { | ||
235 | if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) == 0) | ||
236 | { | ||
237 | if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) | ||
238 | { | ||
239 | GNUNET_SCHEDULER_cancel(shutdown_task); | ||
240 | shutdown_task = GNUNET_SCHEDULER_NO_TASK; | ||
241 | } | ||
242 | } | ||
243 | else | ||
244 | { | ||
245 | shutdown_task = GNUNET_SCHEDULER_NO_TASK ; | ||
246 | } | ||
247 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown requested.\n"); | ||
248 | if (NULL != pg) | ||
249 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
250 | pg = NULL; | ||
251 | } | ||
252 | |||
253 | |||
254 | /** | ||
255 | * Master context for 'stat_run'. | ||
256 | */ | ||
257 | struct StatMaster | ||
258 | { | ||
259 | struct GNUNET_STATISTICS_Handle *stat; | ||
260 | unsigned int daemon; | ||
261 | unsigned int value; | ||
262 | }; | ||
263 | |||
264 | struct StatValues | ||
265 | { | ||
266 | const char *subsystem; | ||
267 | const char *name; | ||
268 | unsigned long long total; | ||
269 | }; | ||
270 | |||
271 | /** | ||
272 | * Statistics we print out. | ||
273 | */ | ||
274 | static struct StatValues stats[] = { | ||
275 | {"core", "# bytes decrypted", 0}, | ||
276 | {"core", "# bytes encrypted", 0}, | ||
277 | {"core", "# type maps received", 0}, | ||
278 | {"core", "# session keys confirmed via PONG", 0}, | ||
279 | {"core", "# peers connected", 0}, | ||
280 | {"core", "# key exchanges initiated", 0}, | ||
281 | {"core", "# send requests dropped (disconnected)", 0}, | ||
282 | {"core", "# transmissions delayed due to corking", 0}, | ||
283 | {"core", "# messages discarded (expired prior to transmission)", 0}, | ||
284 | {"core", "# messages discarded (disconnected)", 0}, | ||
285 | {"core", "# discarded CORE_SEND requests", 0}, | ||
286 | {"core", "# discarded lower priority CORE_SEND requests", 0}, | ||
287 | {"transport", "# bytes received via TCP", 0}, | ||
288 | {"transport", "# bytes transmitted via TCP", 0}, | ||
289 | {"dht", "# PUT messages queued for transmission", 0}, | ||
290 | {"dht", "# P2P PUT requests received", 0}, | ||
291 | {"dht", "# GET messages queued for transmission", 0}, | ||
292 | {"dht", "# P2P GET requests received", 0}, | ||
293 | {"dht", "# RESULT messages queued for transmission", 0}, | ||
294 | {"dht", "# P2P RESULTS received", 0}, | ||
295 | {"dht", "# Queued messages discarded (peer disconnected)", 0}, | ||
296 | {"dht", "# Peers excluded from routing due to Bloomfilter", 0}, | ||
297 | {"dht", "# Peer selection failed", 0}, | ||
298 | {"dht", "# FIND PEER requests ignored due to Bloomfilter", 0}, | ||
299 | {"dht", "# FIND PEER requests ignored due to lack of HELLO", 0}, | ||
300 | {"dht", "# P2P FIND PEER requests processed", 0}, | ||
301 | {"dht", "# P2P GET requests ONLY routed", 0}, | ||
302 | {"dht", "# Preference updates given to core", 0}, | ||
303 | {"dht", "# REPLIES ignored for CLIENTS (no match)", 0}, | ||
304 | {"dht", "# GET requests from clients injected", 0}, | ||
305 | {"dht", "# GET requests received from clients", 0}, | ||
306 | {"dht", "# GET STOP requests received from clients", 0}, | ||
307 | {"dht", "# ITEMS stored in datacache", 0}, | ||
308 | {"dht", "# Good RESULTS found in datacache", 0}, | ||
309 | {"dht", "# GET requests given to datacache", 0}, | ||
310 | {NULL, NULL, 0} | ||
311 | }; | ||
312 | |||
313 | |||
314 | /** | ||
315 | * Callback function to process statistic values. | ||
316 | * | ||
317 | * @param cls closure | ||
318 | * @param subsystem name of subsystem that created the statistic | ||
319 | * @param name the name of the datum | ||
320 | * @param value the current value | ||
321 | * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not | ||
322 | * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration | ||
323 | */ | ||
324 | static int | ||
325 | print_stat (void *cls, const char *subsystem, const char *name, uint64_t value, | ||
326 | int is_persistent) | ||
327 | { | ||
328 | struct StatMaster *sm = cls; | ||
329 | |||
330 | stats[sm->value].total += value; | ||
331 | FPRINTF (stderr, "Peer %2u: %12s/%50s = %12llu\n", sm->daemon, subsystem, | ||
332 | name, (unsigned long long) value); | ||
333 | return GNUNET_OK; | ||
334 | } | ||
335 | |||
336 | |||
337 | /** | ||
338 | * Function that gathers stats from all daemons. | ||
339 | */ | ||
340 | static void | ||
341 | stat_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
342 | |||
343 | |||
344 | /** | ||
345 | * Function called when GET operation on stats is done. | ||
346 | */ | ||
347 | static void | ||
348 | get_done (void *cls, int success) | ||
349 | { | ||
350 | struct StatMaster *sm = cls; | ||
351 | |||
352 | GNUNET_break (GNUNET_OK == success); | ||
353 | sm->value++; | ||
354 | GNUNET_SCHEDULER_add_now (&stat_run, sm); | ||
355 | } | ||
356 | |||
357 | |||
358 | /** | ||
359 | * Function that gathers stats from all daemons. | ||
360 | */ | ||
361 | static void | ||
362 | stat_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
363 | { | ||
364 | struct StatMaster *sm = cls; | ||
365 | unsigned int i; | ||
366 | |||
367 | die_task = GNUNET_SCHEDULER_NO_TASK; | ||
368 | if (stats[sm->value].name != NULL) | ||
369 | { | ||
370 | GNUNET_STATISTICS_get (sm->stat, | ||
371 | #if 0 | ||
372 | NULL, NULL, | ||
373 | #else | ||
374 | stats[sm->value].subsystem, stats[sm->value].name, | ||
375 | #endif | ||
376 | GNUNET_TIME_UNIT_FOREVER_REL, &get_done, &print_stat, | ||
377 | sm); | ||
378 | return; | ||
379 | } | ||
380 | GNUNET_STATISTICS_destroy (sm->stat, GNUNET_NO); | ||
381 | sm->value = 0; | ||
382 | sm->daemon++; | ||
383 | if (sm->daemon == num_peers) | ||
384 | { | ||
385 | GNUNET_free (sm); | ||
386 | i = 0; | ||
387 | while (stats[i].name != NULL) | ||
388 | { | ||
389 | FPRINTF (stderr, "Total : %12s/%50s = %12llu\n", stats[i].subsystem, | ||
390 | stats[i].name, (unsigned long long) stats[i].total); | ||
391 | i++; | ||
392 | } | ||
393 | die_task = GNUNET_SCHEDULER_add_now (&do_stop, NULL); | ||
394 | return; | ||
395 | } | ||
396 | sm->stat = | ||
397 | GNUNET_STATISTICS_create ("<driver>", | ||
398 | GNUNET_TESTING_daemon_get (pg, | ||
399 | sm->daemon)->cfg); | ||
400 | die_task = GNUNET_SCHEDULER_add_now (&stat_run, sm); | ||
401 | } | ||
402 | |||
403 | |||
404 | /** | ||
405 | * Function scheduled to be run on the successful completion of this | ||
406 | * testcase. | ||
407 | */ | ||
408 | static void | ||
409 | finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
410 | { | ||
411 | struct TestPutContext *test_put; | ||
412 | struct TestGetContext *test_get; | ||
413 | struct StatMaster *sm; | ||
414 | |||
415 | die_task = GNUNET_SCHEDULER_NO_TASK; | ||
416 | while (NULL != (test_put = all_puts_head)) | ||
417 | { | ||
418 | if (test_put->task != GNUNET_SCHEDULER_NO_TASK) | ||
419 | GNUNET_SCHEDULER_cancel (test_put->task); | ||
420 | if (test_put->dht_handle != NULL) | ||
421 | GNUNET_DHT_disconnect (test_put->dht_handle); | ||
422 | GNUNET_CONTAINER_DLL_remove (all_puts_head, all_puts_tail, test_put); | ||
423 | GNUNET_free (test_put); | ||
424 | } | ||
425 | |||
426 | while (NULL != (test_get = all_gets_head)) | ||
427 | { | ||
428 | if (test_get->task != GNUNET_SCHEDULER_NO_TASK) | ||
429 | GNUNET_SCHEDULER_cancel (test_get->task); | ||
430 | if (test_get->get_handle != NULL) | ||
431 | GNUNET_DHT_get_stop (test_get->get_handle); | ||
432 | if (test_get->dht_handle != NULL) | ||
433 | GNUNET_DHT_disconnect (test_get->dht_handle); | ||
434 | GNUNET_CONTAINER_DLL_remove (all_gets_head, all_gets_tail, test_get); | ||
435 | GNUNET_free (test_get); | ||
436 | } | ||
437 | sm = GNUNET_malloc (sizeof (struct StatMaster)); | ||
438 | sm->stat = | ||
439 | GNUNET_STATISTICS_create ("<driver>", | ||
440 | GNUNET_TESTING_daemon_get (pg, | ||
441 | sm->daemon)->cfg); | ||
442 | die_task = GNUNET_SCHEDULER_add_now (&stat_run, sm); | ||
443 | } | ||
444 | |||
445 | |||
446 | /** | ||
447 | * Check if the get_handle is being used, if so stop the request. Either | ||
448 | * way, schedule the end_badly_cont function which actually shuts down the | ||
449 | * test. | ||
450 | */ | ||
451 | static void | ||
452 | end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
453 | { | ||
454 | const char *emsg = cls; | ||
455 | struct TestPutContext *test_put; | ||
456 | struct TestGetContext *test_get; | ||
457 | |||
458 | die_task = GNUNET_SCHEDULER_NO_TASK; | ||
459 | FPRINTF (stderr, "Failing test with error: `%s'!\n", emsg); | ||
460 | while (NULL != (test_put = all_puts_head)) | ||
461 | { | ||
462 | if (test_put->task != GNUNET_SCHEDULER_NO_TASK) | ||
463 | GNUNET_SCHEDULER_cancel (test_put->task); | ||
464 | if (test_put->dht_handle != NULL) | ||
465 | GNUNET_DHT_disconnect (test_put->dht_handle); | ||
466 | GNUNET_CONTAINER_DLL_remove (all_puts_head, all_puts_tail, test_put); | ||
467 | GNUNET_free (test_put); | ||
468 | } | ||
469 | |||
470 | while (NULL != (test_get = all_gets_head)) | ||
471 | { | ||
472 | if (test_get->task != GNUNET_SCHEDULER_NO_TASK) | ||
473 | GNUNET_SCHEDULER_cancel (test_get->task); | ||
474 | if (test_get->get_handle != NULL) | ||
475 | GNUNET_DHT_get_stop (test_get->get_handle); | ||
476 | if (test_get->dht_handle != NULL) | ||
477 | GNUNET_DHT_disconnect (test_get->dht_handle); | ||
478 | GNUNET_CONTAINER_DLL_remove (all_gets_head, all_gets_tail, test_get); | ||
479 | GNUNET_free (test_get); | ||
480 | } | ||
481 | ok = 1; | ||
482 | /* testing_peergroup will do that in its own end_badly() handler */ | ||
483 | /*GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); */ | ||
484 | pg = NULL; | ||
485 | } | ||
486 | |||
487 | |||
488 | /** | ||
489 | * Task to release get handle. | ||
490 | */ | ||
491 | static void | ||
492 | get_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
493 | { | ||
494 | struct TestGetContext *test_get = cls; | ||
495 | struct GNUNET_HashCode search_key; /* Key stored under */ | ||
496 | char original_data[TEST_DATA_SIZE]; /* Made up data to store */ | ||
497 | |||
498 | test_get->task = GNUNET_SCHEDULER_NO_TASK; | ||
499 | memset (original_data, test_get->uid, sizeof (original_data)); | ||
500 | GNUNET_CRYPTO_hash (original_data, TEST_DATA_SIZE, &search_key); | ||
501 | if (test_get->succeeded != GNUNET_YES) | ||
502 | { | ||
503 | gets_failed++; | ||
504 | FPRINTF (stderr, "Get from peer %s for key %s failed!\n", | ||
505 | GNUNET_i2s (&test_get->daemon->id), GNUNET_h2s (&search_key)); | ||
506 | } | ||
507 | GNUNET_assert (test_get->get_handle != NULL); | ||
508 | GNUNET_DHT_get_stop (test_get->get_handle); | ||
509 | test_get->get_handle = NULL; | ||
510 | |||
511 | outstanding_gets--; /* GET is really finished */ | ||
512 | GNUNET_DHT_disconnect (test_get->dht_handle); | ||
513 | test_get->dht_handle = NULL; | ||
514 | |||
515 | GNUNET_CONTAINER_DLL_remove (all_gets_head, all_gets_tail, test_get); | ||
516 | GNUNET_free (test_get); | ||
517 | if ((gets_failed > 10) && (outstanding_gets == 0)) | ||
518 | { | ||
519 | /* Had more than 10% failures */ | ||
520 | FPRINTF (stderr, "%llu gets succeeded, %llu gets failed!\n", gets_completed, | ||
521 | gets_failed); | ||
522 | GNUNET_SCHEDULER_cancel (die_task); | ||
523 | ok = 1; | ||
524 | die_task = | ||
525 | GNUNET_SCHEDULER_add_now (&finish_testing, "not all gets succeeded"); | ||
526 | return; | ||
527 | } | ||
528 | if ((gets_completed + gets_failed == num_peers * num_peers) && (outstanding_gets == 0)) /* All gets successful */ | ||
529 | { | ||
530 | FPRINTF (stderr, "%llu gets succeeded, %llu gets failed!\n", gets_completed, | ||
531 | gets_failed); | ||
532 | GNUNET_SCHEDULER_cancel (die_task); | ||
533 | ok = 0; | ||
534 | die_task = GNUNET_SCHEDULER_add_now (&finish_testing, NULL); | ||
535 | } | ||
536 | } | ||
537 | |||
538 | |||
539 | /** | ||
540 | * Iterator called if the GET request initiated returns a response. | ||
541 | * | ||
542 | * @param cls closure | ||
543 | * @param exp when will this value expire | ||
544 | * @param key key of the result | ||
545 | * @param type type of the result | ||
546 | * @param size number of bytes in data | ||
547 | * @param data pointer to the result data | ||
548 | */ | ||
549 | static void | ||
550 | get_result_iterator (void *cls, struct GNUNET_TIME_Absolute exp, | ||
551 | const struct GNUNET_HashCode * key, | ||
552 | const struct GNUNET_PeerIdentity *get_path, | ||
553 | unsigned int get_path_length, | ||
554 | const struct GNUNET_PeerIdentity *put_path, | ||
555 | unsigned int put_path_length, enum GNUNET_BLOCK_Type type, | ||
556 | size_t size, const void *data) | ||
557 | { | ||
558 | struct TestGetContext *test_get = cls; | ||
559 | struct GNUNET_HashCode search_key; /* Key stored under */ | ||
560 | char original_data[TEST_DATA_SIZE]; /* Made up data to store */ | ||
561 | |||
562 | memset (original_data, test_get->uid, sizeof (original_data)); | ||
563 | GNUNET_CRYPTO_hash (original_data, TEST_DATA_SIZE, &search_key); | ||
564 | if (test_get->succeeded == GNUNET_YES) | ||
565 | return; /* Get has already been successful, probably ending now */ | ||
566 | |||
567 | #if PATH_TRACKING | ||
568 | if (put_path != NULL) | ||
569 | { | ||
570 | unsigned int i; | ||
571 | |||
572 | FPRINTF (stderr, "PUT (%u) Path: ", test_get->uid); | ||
573 | for (i = 0; i < put_path_length; i++) | ||
574 | FPRINTF (stderr, "%s%s", i == 0 ? "" : "->", GNUNET_i2s (&put_path[i])); | ||
575 | FPRINTF (stderr, "%s", "\n"); | ||
576 | } | ||
577 | if (get_path != NULL) | ||
578 | { | ||
579 | unsigned int i; | ||
580 | |||
581 | FPRINTF (stderr, "GET (%u) Path: ", test_get->uid); | ||
582 | for (i = 0; i < get_path_length; i++) | ||
583 | FPRINTF (stderr, "%s%s", i == 0 ? "" : "->", GNUNET_i2s (&get_path[i])); | ||
584 | FPRINTF (stderr, "%s%s\n", get_path_length > 0 ? "->" : "", | ||
585 | GNUNET_i2s (&test_get->daemon->id)); | ||
586 | } | ||
587 | #endif | ||
588 | |||
589 | if ((0 != memcmp (&search_key, key, sizeof (struct GNUNET_HashCode))) || | ||
590 | (0 != memcmp (original_data, data, sizeof (original_data)))) | ||
591 | { | ||
592 | FPRINTF (stderr, "%s", "Key or data is not the same as was inserted!\n"); | ||
593 | return; | ||
594 | } | ||
595 | gets_completed++; | ||
596 | test_get->succeeded = GNUNET_YES; | ||
597 | GNUNET_SCHEDULER_cancel (test_get->task); | ||
598 | test_get->task = GNUNET_SCHEDULER_add_now (&get_stop_task, test_get); | ||
599 | } | ||
600 | |||
601 | |||
602 | /** | ||
603 | * Set up some data, and call API PUT function | ||
604 | */ | ||
605 | static void | ||
606 | do_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
607 | { | ||
608 | struct TestGetContext *test_get = cls; | ||
609 | struct GNUNET_HashCode key; /* Made up key to store data under */ | ||
610 | char data[TEST_DATA_SIZE]; /* Made up data to store */ | ||
611 | |||
612 | if (outstanding_gets > MAX_OUTSTANDING_GETS) | ||
613 | { | ||
614 | test_get->task = | ||
615 | GNUNET_SCHEDULER_add_delayed (GET_DELAY, &do_get, test_get); | ||
616 | return; | ||
617 | } | ||
618 | memset (data, test_get->uid, sizeof (data)); | ||
619 | GNUNET_CRYPTO_hash (data, TEST_DATA_SIZE, &key); | ||
620 | test_get->dht_handle = GNUNET_DHT_connect (test_get->daemon->cfg, 10); | ||
621 | GNUNET_assert (test_get->dht_handle != NULL); | ||
622 | outstanding_gets++; | ||
623 | test_get->get_handle = | ||
624 | GNUNET_DHT_get_start (test_get->dht_handle, | ||
625 | GNUNET_BLOCK_TYPE_TEST, &key, 1, route_option, NULL, | ||
626 | 0, &get_result_iterator, test_get); | ||
627 | test_get->task = | ||
628 | GNUNET_SCHEDULER_add_delayed (GET_TIMEOUT, &get_stop_task, test_get); | ||
629 | } | ||
630 | |||
631 | |||
632 | /** | ||
633 | * Task to release DHT handles for PUT | ||
634 | */ | ||
635 | static void | ||
636 | put_disconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
637 | { | ||
638 | struct TestPutContext *test_put = cls; | ||
639 | |||
640 | test_put->task = GNUNET_SCHEDULER_NO_TASK; | ||
641 | GNUNET_DHT_disconnect (test_put->dht_handle); | ||
642 | test_put->dht_handle = NULL; | ||
643 | GNUNET_CONTAINER_DLL_remove (all_puts_head, all_puts_tail, test_put); | ||
644 | GNUNET_free (test_put); | ||
645 | } | ||
646 | |||
647 | |||
648 | /** | ||
649 | * Schedule the GET requests | ||
650 | */ | ||
651 | static void | ||
652 | start_gets (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
653 | { | ||
654 | unsigned long long i; | ||
655 | unsigned long long j; | ||
656 | struct TestGetContext *test_get; | ||
657 | |||
658 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
659 | "Issuing %llu GETs\n", | ||
660 | (unsigned long long) (num_peers * num_peers)); | ||
661 | for (i = 0; i < num_peers; i++) | ||
662 | for (j = 0; j < num_peers; j++) | ||
663 | { | ||
664 | test_get = GNUNET_malloc (sizeof (struct TestGetContext)); | ||
665 | test_get->uid = i + j * num_peers; | ||
666 | test_get->daemon = GNUNET_TESTING_daemon_get (pg, j); | ||
667 | GNUNET_CONTAINER_DLL_insert (all_gets_head, all_gets_tail, test_get); | ||
668 | test_get->task = GNUNET_SCHEDULER_add_now (&do_get, test_get); | ||
669 | } | ||
670 | } | ||
671 | |||
672 | |||
673 | /** | ||
674 | * Called when the PUT request has been transmitted to the DHT service. | ||
675 | */ | ||
676 | static void | ||
677 | put_finished (void *cls, int success) | ||
678 | { | ||
679 | struct TestPutContext *test_put = cls; | ||
680 | |||
681 | outstanding_puts--; | ||
682 | puts_completed++; | ||
683 | if (GNUNET_SCHEDULER_NO_TASK != test_put->task) | ||
684 | { | ||
685 | GNUNET_SCHEDULER_cancel (test_put->task); | ||
686 | } | ||
687 | test_put->task = GNUNET_SCHEDULER_add_now (&put_disconnect_task, test_put); | ||
688 | if (puts_completed != num_peers * num_peers) | ||
689 | return; | ||
690 | |||
691 | GNUNET_assert (outstanding_puts == 0); | ||
692 | GNUNET_SCHEDULER_add_delayed (START_DELAY, &start_gets, NULL); | ||
693 | } | ||
694 | |||
695 | |||
696 | /** | ||
697 | * Set up some data, and call API PUT function | ||
698 | */ | ||
699 | static void | ||
700 | do_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
701 | { | ||
702 | struct TestPutContext *test_put = cls; | ||
703 | struct GNUNET_HashCode key; /* Made up key to store data under */ | ||
704 | char data[TEST_DATA_SIZE]; /* Made up data to store */ | ||
705 | |||
706 | test_put->task = GNUNET_SCHEDULER_NO_TASK; | ||
707 | if (outstanding_puts > MAX_OUTSTANDING_PUTS) | ||
708 | { | ||
709 | test_put->task = | ||
710 | GNUNET_SCHEDULER_add_delayed (PUT_DELAY, &do_put, test_put); | ||
711 | return; | ||
712 | } | ||
713 | memset (data, test_put->uid, sizeof (data)); | ||
714 | GNUNET_CRYPTO_hash (data, TEST_DATA_SIZE, &key); | ||
715 | test_put->dht_handle = GNUNET_DHT_connect (test_put->daemon->cfg, 10); | ||
716 | GNUNET_assert (test_put->dht_handle != NULL); | ||
717 | outstanding_puts++; | ||
718 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
719 | "PUT %u at `%s'\n", test_put->uid, | ||
720 | GNUNET_i2s (&test_put->daemon->id)); | ||
721 | GNUNET_DHT_put (test_put->dht_handle, &key, 1, route_option, | ||
722 | GNUNET_BLOCK_TYPE_TEST, sizeof (data), data, | ||
723 | GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_TIME_UNIT_FOREVER_REL, | ||
724 | &put_finished, test_put); | ||
725 | test_put->task = | ||
726 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, | ||
727 | &put_disconnect_task, test_put); | ||
728 | } | ||
729 | |||
730 | |||
731 | static void | ||
732 | run_dht_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
733 | { | ||
734 | unsigned long long i; | ||
735 | struct TestPutContext *test_put; | ||
736 | |||
737 | if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | ||
738 | { | ||
739 | ok = 1; | ||
740 | return; | ||
741 | } | ||
742 | #if PATH_TRACKING | ||
743 | route_option = | ||
744 | GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE; | ||
745 | #else | ||
746 | route_option = GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE; | ||
747 | #endif | ||
748 | die_task = | ||
749 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, | ||
750 | "from setup puts/gets"); | ||
751 | FPRINTF (stderr, "Issuing %llu PUTs (one per peer)\n", | ||
752 | (unsigned long long) (num_peers * num_peers)); | ||
753 | for (i = 0; i < num_peers * num_peers; i++) | ||
754 | { | ||
755 | test_put = GNUNET_malloc (sizeof (struct TestPutContext)); | ||
756 | test_put->uid = i; | ||
757 | test_put->daemon = GNUNET_TESTING_daemon_get (pg, i % num_peers); | ||
758 | test_put->task = GNUNET_SCHEDULER_add_now (&do_put, test_put); | ||
759 | GNUNET_CONTAINER_DLL_insert (all_puts_head, all_puts_tail, test_put); | ||
760 | } | ||
761 | } | ||
762 | |||
763 | |||
764 | /** | ||
765 | * This function is called once testing has finished setting up the topology. | ||
766 | * | ||
767 | * @param cls unused | ||
768 | * @param emsg variable is NULL on success (peers connected), and non-NULL on | ||
769 | * failure (peers failed to connect). | ||
770 | */ | ||
771 | static void | ||
772 | startup_done (void *cls, const char *emsg) | ||
773 | { | ||
774 | if (emsg != NULL) | ||
775 | { | ||
776 | FPRINTF (stderr, "Failed to setup topology: %s\n", emsg); | ||
777 | die_task = GNUNET_SCHEDULER_add_now (&end_badly, "topology setup failed"); | ||
778 | return; | ||
779 | } | ||
780 | die_task = | ||
781 | GNUNET_SCHEDULER_add_delayed (START_DELAY, &run_dht_test, | ||
782 | "from setup puts/gets"); | ||
783 | } | ||
784 | |||
785 | |||
786 | static void | ||
787 | run (void *cls, char *const *args, const char *cfgfile, | ||
788 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
789 | { | ||
790 | /* Get path from configuration file */ | ||
791 | if (GNUNET_YES != | ||
792 | GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", | ||
793 | &test_directory)) | ||
794 | { | ||
795 | GNUNET_break (0); | ||
796 | ok = 404; | ||
797 | return; | ||
798 | } | ||
799 | if (GNUNET_SYSERR == | ||
800 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing_old", "num_peers", | ||
801 | &num_peers)) | ||
802 | num_peers = DEFAULT_NUM_PEERS; | ||
803 | pg = GNUNET_TESTING_peergroup_start (cfg, num_peers, TIMEOUT, NULL, | ||
804 | &startup_done, NULL, NULL); | ||
805 | GNUNET_assert (NULL != pg); | ||
806 | shutdown_task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_FOREVER_REL, | ||
807 | &do_stop, NULL); | ||
808 | } | ||
809 | |||
810 | |||
811 | static int | ||
812 | check () | ||
813 | { | ||
814 | int ret; | ||
815 | |||
816 | /* Arguments for GNUNET_PROGRAM_run */ | ||
817 | char *const argv[] = { "test-dht-multipeer", /* Name to give running binary */ | ||
818 | "-c", | ||
819 | "test_dht_multipeer_data.conf", /* Config file to use */ | ||
820 | NULL | ||
821 | }; | ||
822 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
823 | GNUNET_GETOPT_OPTION_END | ||
824 | }; | ||
825 | /* Run the run function as a new program */ | ||
826 | ret = | ||
827 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, | ||
828 | "test-dht-multipeer", "nohelp", options, &run, &ok); | ||
829 | if (ret != GNUNET_OK) | ||
830 | { | ||
831 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
832 | "`test-dht-multipeer': Failed with error code %d\n", ret); | ||
833 | } | ||
834 | return ok; | ||
835 | } | ||
836 | |||
837 | |||
838 | int | ||
839 | main (int argc, char *argv[]) | ||
840 | { | ||
841 | int ret; | ||
842 | |||
843 | GNUNET_log_setup ("test-dht-multipeer", | ||
844 | "WARNING", | ||
845 | NULL); | ||
846 | ret = check (); | ||
847 | /** | ||
848 | * Need to remove base directory, subdirectories taken care | ||
849 | * of by the testing framework. | ||
850 | */ | ||
851 | if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK) | ||
852 | { | ||
853 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
854 | "Failed to remove testing directory %s\n", test_directory); | ||
855 | } | ||
856 | return ret; | ||
857 | } | ||
858 | |||
859 | /* end of test_dht_multipeer.c */ | ||
diff --git a/src/dht/test_dht_twopeer_data.conf b/src/dht/test_dht_multipeer.conf index 51e7a6b8e..497510ce5 100644 --- a/src/dht/test_dht_twopeer_data.conf +++ b/src/dht/test_dht_multipeer.conf | |||
@@ -1,18 +1,11 @@ | |||
1 | [PATHS] | 1 | [fs] |
2 | SERVICEHOME = /tmp/test-dht-twopeer/ | 2 | AUTOSTART = NO |
3 | 3 | ||
4 | [resolver] | 4 | [resolver] |
5 | AUTOSTART = YES | 5 | AUTOSTART = NO |
6 | |||
7 | [dht] | ||
8 | DEBUG = NO | ||
9 | AUTOSTART = YES | ||
10 | #PREFIX = xterm -T dht -e gdb --args | ||
11 | PORT = 12100 | ||
12 | BINARY = gnunet-service-dht | ||
13 | 6 | ||
14 | [block] | 7 | [block] |
15 | plugins = test dht dns | 8 | plugins = test dht |
16 | 9 | ||
17 | [dhtcache] | 10 | [dhtcache] |
18 | QUOTA = 1 MB | 11 | QUOTA = 1 MB |
@@ -20,38 +13,27 @@ DATABASE = sqlite | |||
20 | 13 | ||
21 | [transport] | 14 | [transport] |
22 | PLUGINS = tcp | 15 | PLUGINS = tcp |
23 | DEBUG = NO | ||
24 | NEIGHBOUR_LIMIT = 50 | ||
25 | PORT = 12365 | ||
26 | 16 | ||
27 | [ats] | 17 | [ats] |
28 | WAN_QUOTA_IN = 1 GB | 18 | WAN_QUOTA_IN = 1 GB |
29 | WAN_QUOTA_OUT = 1 GB | 19 | WAN_QUOTA_OUT = 1 GB |
30 | 20 | ||
31 | [core] | ||
32 | HOSTNAME = localhost | ||
33 | PORT = 12092 | ||
34 | |||
35 | [arm] | 21 | [arm] |
36 | DEFAULTSERVICES = core dht | 22 | DEFAULTSERVICES = dht core |
37 | PORT = 12366 | ||
38 | DEBUG = NO | ||
39 | |||
40 | [transport-tcp] | ||
41 | TIMEOUT = 300 s | ||
42 | PORT = 12368 | ||
43 | BINDTO = 127.0.0.1 | ||
44 | 23 | ||
45 | [TESTING] | 24 | [TESTING] |
46 | WEAKRANDOM = YES | 25 | WEAKRANDOM = YES |
47 | 26 | ||
48 | [testing_old] | 27 | [testbed] |
49 | NUM_PEERS = 2 | 28 | OVERLAY_TOPOLOGY = FROM_FILE |
50 | HOSTKEYSFILE = ${DATADIR}/testing_hostkeys.dat | 29 | OVERLAY_TOPOLOGY_FILE = test_dht_multipeer_topology.dat |
51 | 30 | ||
52 | [gnunetd] | 31 | [gnunetd] |
53 | HOSTKEY = $SERVICEHOME/.hostkey | 32 | HOSTKEY = $SERVICEHOME/.hostkey |
54 | 33 | ||
34 | [PATHS] | ||
35 | SERVICEHOME = /tmp/test-dht-multipeer/ | ||
36 | |||
55 | [nat] | 37 | [nat] |
56 | DISABLEV6 = YES | 38 | DISABLEV6 = YES |
57 | ENABLE_UPNP = NO | 39 | ENABLE_UPNP = NO |
@@ -64,17 +46,12 @@ USE_LOCALADDR = YES | |||
64 | [dns] | 46 | [dns] |
65 | AUTOSTART = NO | 47 | AUTOSTART = NO |
66 | 48 | ||
67 | [mesh] | 49 | [namestore] |
68 | AUTOSTART = NO | 50 | AUTOSTART = NO |
69 | 51 | ||
70 | [nse] | 52 | [nse] |
71 | AUTOSTART = NO | 53 | AUTOSTART = NO |
72 | 54 | ||
73 | [fs] | ||
74 | AUTOSTART = NO | ||
75 | |||
76 | [namestore] | ||
77 | AUTOSTART = NO | ||
78 | [vpn] | 55 | [vpn] |
79 | AUTOSTART=NO | 56 | AUTOSTART=NO |
80 | 57 | ||
diff --git a/src/dht/test_dht_multipeer_data.conf b/src/dht/test_dht_multipeer_data.conf deleted file mode 100644 index 999ed3807..000000000 --- a/src/dht/test_dht_multipeer_data.conf +++ /dev/null | |||
@@ -1,130 +0,0 @@ | |||
1 | [fs] | ||
2 | AUTOSTART = NO | ||
3 | |||
4 | [resolver] | ||
5 | AUTOSTART = NO | ||
6 | |||
7 | [dht] | ||
8 | DEBUG = NO | ||
9 | STOP_ON_CLOSEST = YES | ||
10 | AUTOSTART = YES | ||
11 | ACCEPT_FROM6 = ::1; | ||
12 | ACCEPT_FROM = 127.0.0.1; | ||
13 | #BINARY = /home/mrwiggles/documents/research/gnunet/gnunet-ng/src/dht/.libs/gnunet-service-dht | ||
14 | #PREFIX = xterm -T dht -e gdb --args | ||
15 | #PREFIX = valgrind --log-file=dht_%p | ||
16 | HOME = $SERVICEHOME | ||
17 | HOSTNAME = localhost | ||
18 | PORT = 12100 | ||
19 | STOP_FOUND = YES | ||
20 | USE_MAX_HOPS = YES | ||
21 | MAX_HOPS = 16 | ||
22 | CONVERGE_BINARY = YES | ||
23 | CONVERGE_MODIFIER = 4 | ||
24 | |||
25 | [block] | ||
26 | plugins = test dht | ||
27 | |||
28 | [dhtcache] | ||
29 | QUOTA = 1 MB | ||
30 | DATABASE = sqlite | ||
31 | |||
32 | [transport] | ||
33 | PLUGINS = tcp | ||
34 | DEBUG = NO | ||
35 | ACCEPT_FROM6 = ::1; | ||
36 | ACCEPT_FROM = 127.0.0.1; | ||
37 | NEIGHBOUR_LIMIT = 50 | ||
38 | BINARY = gnunet-service-transport | ||
39 | HOME = $SERVICEHOME | ||
40 | HOSTNAME = localhost | ||
41 | PORT = 12365 | ||
42 | |||
43 | [DHTLOG] | ||
44 | PLUGIN = mysql_dump | ||
45 | |||
46 | [ats] | ||
47 | WAN_QUOTA_IN = 1 GB | ||
48 | WAN_QUOTA_OUT = 1 GB | ||
49 | |||
50 | [core] | ||
51 | ACCEPT_FROM6 = ::1; | ||
52 | ACCEPT_FROM = 127.0.0.1; | ||
53 | BINARY = gnunet-service-core | ||
54 | HOME = $SERVICEHOME | ||
55 | HOSTNAME = localhost | ||
56 | PORT = 12092 | ||
57 | DEBUG = NO | ||
58 | |||
59 | [arm] | ||
60 | DEFAULTSERVICES = dht core | ||
61 | ACCEPT_FROM6 = ::1; | ||
62 | ACCEPT_FROM = 127.0.0.1; | ||
63 | BINARY = gnunet-service-arm | ||
64 | HOME = $SERVICEHOME | ||
65 | HOSTNAME = localhost | ||
66 | PORT = 12366 | ||
67 | DEBUG = NO | ||
68 | |||
69 | [transport-tcp] | ||
70 | TIMEOUT = 300 s | ||
71 | PORT = 12368 | ||
72 | BINDTO = 127.0.0.1 | ||
73 | |||
74 | [DHT_TESTING] | ||
75 | MYSQL_LOGGING_EXTENDED = NO | ||
76 | MYSQL_LOGGING = NO | ||
77 | NUM_GETS = 5 | ||
78 | NUM_PUTS = 5 | ||
79 | |||
80 | [TESTING] | ||
81 | WEAKRANDOM = YES | ||
82 | |||
83 | [testing_old] | ||
84 | TOPOLOGY = FROM_FILE | ||
85 | # file contains a ring | ||
86 | CONNECT_TOPOLOGY = NONE | ||
87 | # None == use all allowed connections | ||
88 | # BLACKLIST_TOPOLOGY = X | ||
89 | # No additional restrictions... | ||
90 | |||
91 | TOPOLOGY_FILE = multipeer_topo.dat | ||
92 | MAX_CONCURRENT_SSH = 1 | ||
93 | PEERGROUP_TIMEOUT = 2400 s | ||
94 | USE_PROGRESSBARS = YES | ||
95 | #CONNECT_TOPOLOGY_OPTION = CONNECT_RANDOM_SUBSET | ||
96 | #CONNECT_TOPOLOGY_OPTION_MODIFIER = 2 | ||
97 | #LOGNMODIFIER = .65 | ||
98 | #PERCENTAGE = .75 | ||
99 | NUM_PEERS = 10 | ||
100 | HOSTKEYSFILE = ${DATADIR}/testing_hostkeys.dat | ||
101 | |||
102 | [gnunetd] | ||
103 | HOSTKEY = $SERVICEHOME/.hostkey | ||
104 | |||
105 | [PATHS] | ||
106 | SERVICEHOME = /tmp/test-dht-multipeer/ | ||
107 | |||
108 | [nat] | ||
109 | DISABLEV6 = YES | ||
110 | ENABLE_UPNP = NO | ||
111 | BEHIND_NAT = NO | ||
112 | ALLOW_NAT = NO | ||
113 | INTERNAL_ADDRESS = 127.0.0.1 | ||
114 | EXTERNAL_ADDRESS = 127.0.0.1 | ||
115 | USE_LOCALADDR = YES | ||
116 | |||
117 | [dns] | ||
118 | AUTOSTART = NO | ||
119 | |||
120 | [namestore] | ||
121 | AUTOSTART = NO | ||
122 | |||
123 | [nse] | ||
124 | AUTOSTART = NO | ||
125 | |||
126 | |||
127 | [vpn] | ||
128 | AUTOSTART=NO | ||
129 | |||
130 | |||
diff --git a/src/dht/multipeer_topo.dat b/src/dht/test_dht_multipeer_topology.dat index 1233e6b66..1233e6b66 100644 --- a/src/dht/multipeer_topo.dat +++ b/src/dht/test_dht_multipeer_topology.dat | |||
diff --git a/src/dht/test_dht_topo.c b/src/dht/test_dht_topo.c index 0934d7abd..c9036d2c1 100644 --- a/src/dht/test_dht_topo.c +++ b/src/dht/test_dht_topo.c | |||
@@ -30,11 +30,6 @@ | |||
30 | #include "dht_test_lib.h" | 30 | #include "dht_test_lib.h" |
31 | 31 | ||
32 | /** | 32 | /** |
33 | * Number of peers to run. | ||
34 | */ | ||
35 | #define NUM_PEERS 5 | ||
36 | |||
37 | /** | ||
38 | * How long until we give up on fetching the data? | 33 | * How long until we give up on fetching the data? |
39 | */ | 34 | */ |
40 | #define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) | 35 | #define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) |
@@ -93,6 +88,131 @@ static struct GetOperation *get_head; | |||
93 | */ | 88 | */ |
94 | static struct GetOperation *get_tail; | 89 | static struct GetOperation *get_tail; |
95 | 90 | ||
91 | /** | ||
92 | * Array of the testbed's peers. | ||
93 | */ | ||
94 | static struct GNUNET_TESTBED_Peer **my_peers; | ||
95 | |||
96 | /** | ||
97 | * Number of peers to run. | ||
98 | */ | ||
99 | static unsigned int NUM_PEERS; | ||
100 | |||
101 | |||
102 | /** | ||
103 | * Statistics we print out. | ||
104 | */ | ||
105 | static struct | ||
106 | { | ||
107 | const char *subsystem; | ||
108 | const char *name; | ||
109 | unsigned long long total; | ||
110 | } stats[] = { | ||
111 | {"core", "# bytes decrypted", 0}, | ||
112 | {"core", "# bytes encrypted", 0}, | ||
113 | {"core", "# type maps received", 0}, | ||
114 | {"core", "# session keys confirmed via PONG", 0}, | ||
115 | {"core", "# peers connected", 0}, | ||
116 | {"core", "# key exchanges initiated", 0}, | ||
117 | {"core", "# send requests dropped (disconnected)", 0}, | ||
118 | {"core", "# transmissions delayed due to corking", 0}, | ||
119 | {"core", "# messages discarded (expired prior to transmission)", 0}, | ||
120 | {"core", "# messages discarded (disconnected)", 0}, | ||
121 | {"core", "# discarded CORE_SEND requests", 0}, | ||
122 | {"core", "# discarded lower priority CORE_SEND requests", 0}, | ||
123 | {"transport", "# bytes received via TCP", 0}, | ||
124 | {"transport", "# bytes transmitted via TCP", 0}, | ||
125 | {"dht", "# PUT messages queued for transmission", 0}, | ||
126 | {"dht", "# P2P PUT requests received", 0}, | ||
127 | {"dht", "# GET messages queued for transmission", 0}, | ||
128 | {"dht", "# P2P GET requests received", 0}, | ||
129 | {"dht", "# RESULT messages queued for transmission", 0}, | ||
130 | {"dht", "# P2P RESULTS received", 0}, | ||
131 | {"dht", "# Queued messages discarded (peer disconnected)", 0}, | ||
132 | {"dht", "# Peers excluded from routing due to Bloomfilter", 0}, | ||
133 | {"dht", "# Peer selection failed", 0}, | ||
134 | {"dht", "# FIND PEER requests ignored due to Bloomfilter", 0}, | ||
135 | {"dht", "# FIND PEER requests ignored due to lack of HELLO", 0}, | ||
136 | {"dht", "# P2P FIND PEER requests processed", 0}, | ||
137 | {"dht", "# P2P GET requests ONLY routed", 0}, | ||
138 | {"dht", "# Preference updates given to core", 0}, | ||
139 | {"dht", "# REPLIES ignored for CLIENTS (no match)", 0}, | ||
140 | {"dht", "# GET requests from clients injected", 0}, | ||
141 | {"dht", "# GET requests received from clients", 0}, | ||
142 | {"dht", "# GET STOP requests received from clients", 0}, | ||
143 | {"dht", "# ITEMS stored in datacache", 0}, | ||
144 | {"dht", "# Good RESULTS found in datacache", 0}, | ||
145 | {"dht", "# GET requests given to datacache", 0}, | ||
146 | {NULL, NULL, 0} | ||
147 | }; | ||
148 | |||
149 | |||
150 | /** | ||
151 | * Function called once we're done processing stats. | ||
152 | * | ||
153 | * @param cls the test context | ||
154 | * @param op the stats operation | ||
155 | * @param emsg error message on failure | ||
156 | */ | ||
157 | static void | ||
158 | stats_finished (void *cls, | ||
159 | struct GNUNET_TESTBED_Operation *op, | ||
160 | const char *emsg) | ||
161 | { | ||
162 | struct GNUNET_DHT_TEST_Context *ctx = cls; | ||
163 | unsigned int i; | ||
164 | |||
165 | if (NULL != op) | ||
166 | GNUNET_TESTBED_operation_done (op); // needed? | ||
167 | if (NULL != emsg) | ||
168 | { | ||
169 | fprintf (stderr, _("Gathering statistics failed: %s\n"), | ||
170 | emsg); | ||
171 | GNUNET_SCHEDULER_cancel (put_task); | ||
172 | GNUNET_DHT_TEST_cleanup (ctx); | ||
173 | return; | ||
174 | } | ||
175 | for (i = 0; NULL != stats[i].name; i++) | ||
176 | FPRINTF (stderr, | ||
177 | "%6s/%60s = %12llu\n", | ||
178 | stats[i].subsystem, | ||
179 | stats[i].name, | ||
180 | stats[i].total); | ||
181 | GNUNET_SCHEDULER_cancel (put_task); | ||
182 | GNUNET_DHT_TEST_cleanup (ctx); | ||
183 | } | ||
184 | |||
185 | |||
186 | /** | ||
187 | * Function called to process statistic values from all peers. | ||
188 | * | ||
189 | * @param cls closure | ||
190 | * @param peer the peer the statistic belong to | ||
191 | * @param subsystem name of subsystem that created the statistic | ||
192 | * @param name the name of the datum | ||
193 | * @param value the current value | ||
194 | * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not | ||
195 | * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration | ||
196 | */ | ||
197 | static int | ||
198 | handle_stats (void *cls, | ||
199 | const struct GNUNET_TESTBED_Peer *peer, | ||
200 | const char *subsystem, | ||
201 | const char *name, | ||
202 | uint64_t value, | ||
203 | int is_persistent) | ||
204 | { | ||
205 | unsigned int i; | ||
206 | |||
207 | for (i = 0; NULL != stats[i].name; i++) | ||
208 | if ( (0 == strcasecmp (subsystem, | ||
209 | stats[i].subsystem)) && | ||
210 | (0 == strcasecmp (name, | ||
211 | stats[i].name)) ) | ||
212 | stats[i].total += value; | ||
213 | return GNUNET_OK; | ||
214 | } | ||
215 | |||
96 | 216 | ||
97 | /** | 217 | /** |
98 | * Task run on success or timeout to clean up. | 218 | * Task run on success or timeout to clean up. |
@@ -117,8 +237,11 @@ shutdown_task (void *cls, | |||
117 | get_op); | 237 | get_op); |
118 | GNUNET_free (get_op); | 238 | GNUNET_free (get_op); |
119 | } | 239 | } |
120 | GNUNET_SCHEDULER_cancel (put_task); | 240 | (void) GNUNET_TESTBED_get_statistics (NUM_PEERS, |
121 | GNUNET_DHT_TEST_cleanup (ctx); | 241 | my_peers, |
242 | &handle_stats, | ||
243 | &stats_finished, | ||
244 | ctx); | ||
122 | } | 245 | } |
123 | 246 | ||
124 | 247 | ||
@@ -249,16 +372,9 @@ run (void *cls, | |||
249 | struct GetOperation *get_op; | 372 | struct GetOperation *get_op; |
250 | 373 | ||
251 | GNUNET_assert (NUM_PEERS == num_peers); | 374 | GNUNET_assert (NUM_PEERS == num_peers); |
375 | my_peers = peers; | ||
252 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 376 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
253 | "Peers setup, starting test\n"); | 377 | "Peers setup, starting test\n"); |
254 | /* FIXME: once testbed is finished, this call should | ||
255 | no longer be needed */ | ||
256 | GNUNET_TESTBED_overlay_configure_topology (NULL, | ||
257 | num_peers, | ||
258 | peers, | ||
259 | GNUNET_TESTBED_TOPOLOGY_LINE, | ||
260 | GNUNET_TESTBED_TOPOLOGY_OPTION_END); | ||
261 | |||
262 | put_task = GNUNET_SCHEDULER_add_now (&do_puts, dhts); | 378 | put_task = GNUNET_SCHEDULER_add_now (&do_puts, dhts); |
263 | for (i=0;i<num_peers;i++) | 379 | for (i=0;i<num_peers;i++) |
264 | { | 380 | { |
@@ -297,11 +413,25 @@ main (int xargc, char *xargv[]) | |||
297 | { | 413 | { |
298 | cfg_filename = "test_dht_2dtorus.conf"; | 414 | cfg_filename = "test_dht_2dtorus.conf"; |
299 | test_name = "test-dht-2dtorus"; | 415 | test_name = "test-dht-2dtorus"; |
416 | NUM_PEERS = 16; | ||
300 | } | 417 | } |
301 | else if (NULL != strstr (xargv[0], "test_dht_line")) | 418 | else if (NULL != strstr (xargv[0], "test_dht_line")) |
302 | { | 419 | { |
303 | cfg_filename = "test_dht_line.conf"; | 420 | cfg_filename = "test_dht_line.conf"; |
304 | test_name = "test-dht-line"; | 421 | test_name = "test-dht-line"; |
422 | NUM_PEERS = 5; | ||
423 | } | ||
424 | else if (NULL != strstr (xargv[0], "test_dht_twopeer")) | ||
425 | { | ||
426 | cfg_filename = "test_dht_line.conf"; | ||
427 | test_name = "test-dht-twopeer"; | ||
428 | NUM_PEERS = 2; | ||
429 | } | ||
430 | else if (NULL != strstr (xargv[0], "test_dht_multipeer")) | ||
431 | { | ||
432 | cfg_filename = "test_dht_multipeer.conf"; | ||
433 | test_name = "test-dht-multipeer"; | ||
434 | NUM_PEERS = 10; | ||
305 | } | 435 | } |
306 | else | 436 | else |
307 | { | 437 | { |
diff --git a/src/dht/test_dht_twopeer.c b/src/dht/test_dht_twopeer.c deleted file mode 100644 index 8579013e3..000000000 --- a/src/dht/test_dht_twopeer.c +++ /dev/null | |||
@@ -1,494 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009 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 | * @file dht/test_dht_twopeer.c | ||
22 | * @brief base testcase for testing DHT service with | ||
23 | * two running peers | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_testing_lib.h" | ||
27 | #include "gnunet_core_service.h" | ||
28 | #include "gnunet_dht_service.h" | ||
29 | |||
30 | /* DEFINES */ | ||
31 | #define MAX_GET_ATTEMPTS 10 | ||
32 | |||
33 | #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5) | ||
34 | |||
35 | #define DEFAULT_NUM_PEERS 2 | ||
36 | |||
37 | /* Structs */ | ||
38 | |||
39 | struct PeerGetContext | ||
40 | { | ||
41 | struct GNUNET_PeerIdentity *peer; | ||
42 | |||
43 | struct GNUNET_DHT_Handle *dht_handle; | ||
44 | |||
45 | struct GNUNET_DHT_GetHandle *get_handle; | ||
46 | |||
47 | unsigned int get_attempts; | ||
48 | |||
49 | GNUNET_SCHEDULER_TaskIdentifier retry_task; | ||
50 | }; | ||
51 | |||
52 | /* Globals */ | ||
53 | static char *test_directory; | ||
54 | |||
55 | static struct PeerGetContext curr_get_ctx; | ||
56 | |||
57 | static unsigned int expected_connections; | ||
58 | |||
59 | static unsigned long long peers_left; | ||
60 | |||
61 | static struct GNUNET_TESTING_PeerGroup *pg; | ||
62 | |||
63 | static unsigned long long num_peers; | ||
64 | |||
65 | static unsigned int total_gets; | ||
66 | |||
67 | static unsigned int gets_succeeded; | ||
68 | |||
69 | static unsigned int total_connections; | ||
70 | |||
71 | static unsigned int failed_connections; | ||
72 | |||
73 | static GNUNET_SCHEDULER_TaskIdentifier die_task; | ||
74 | |||
75 | static int ok; | ||
76 | |||
77 | static struct GNUNET_PeerIdentity peer1id; | ||
78 | |||
79 | static struct GNUNET_PeerIdentity peer2id; | ||
80 | |||
81 | static struct GNUNET_DHT_Handle *peer1dht; | ||
82 | |||
83 | static struct GNUNET_DHT_Handle *peer2dht; | ||
84 | |||
85 | /** | ||
86 | * Check whether peers successfully shut down. | ||
87 | */ | ||
88 | static void | ||
89 | shutdown_callback (void *cls, const char *emsg) | ||
90 | { | ||
91 | if (emsg != NULL) | ||
92 | { | ||
93 | if (ok == 0) | ||
94 | ok = 2; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | static void | ||
99 | finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
100 | { | ||
101 | GNUNET_assert (pg != NULL); | ||
102 | GNUNET_assert (peer1dht != NULL); | ||
103 | GNUNET_assert (peer2dht != NULL); | ||
104 | GNUNET_DHT_disconnect (peer1dht); | ||
105 | GNUNET_DHT_disconnect (peer2dht); | ||
106 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
107 | pg = NULL; | ||
108 | ok = 0; | ||
109 | } | ||
110 | |||
111 | static void | ||
112 | end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
113 | { | ||
114 | if (peer1dht != NULL) | ||
115 | GNUNET_DHT_disconnect (peer1dht); | ||
116 | |||
117 | if (peer2dht != NULL) | ||
118 | GNUNET_DHT_disconnect (peer2dht); | ||
119 | |||
120 | if (pg != NULL) | ||
121 | { | ||
122 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
123 | pg = NULL; | ||
124 | } | ||
125 | |||
126 | if (curr_get_ctx.retry_task != GNUNET_SCHEDULER_NO_TASK) | ||
127 | { | ||
128 | GNUNET_SCHEDULER_cancel (curr_get_ctx.retry_task); | ||
129 | curr_get_ctx.retry_task = GNUNET_SCHEDULER_NO_TASK; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | |||
134 | static void | ||
135 | end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
136 | { | ||
137 | const char *emsg = cls; | ||
138 | |||
139 | FPRINTF (stderr, "Error: %s\n", emsg); | ||
140 | if (curr_get_ctx.retry_task != GNUNET_SCHEDULER_NO_TASK) | ||
141 | { | ||
142 | GNUNET_SCHEDULER_cancel (curr_get_ctx.retry_task); | ||
143 | curr_get_ctx.retry_task = GNUNET_SCHEDULER_NO_TASK; | ||
144 | } | ||
145 | if (curr_get_ctx.get_handle != NULL) | ||
146 | { | ||
147 | GNUNET_DHT_get_stop (curr_get_ctx.get_handle); | ||
148 | } | ||
149 | |||
150 | GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL); | ||
151 | ok = 1; | ||
152 | } | ||
153 | |||
154 | |||
155 | /* Forward declaration */ | ||
156 | static void | ||
157 | do_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
158 | |||
159 | /** | ||
160 | * Iterator called on each result obtained for a DHT | ||
161 | * operation that expects a reply | ||
162 | * | ||
163 | * @param cls closure | ||
164 | * @param exp when will this value expire | ||
165 | * @param key key of the result | ||
166 | * @param type type of the result | ||
167 | * @param size number of bytes in data | ||
168 | * @param data pointer to the result data | ||
169 | */ | ||
170 | static void | ||
171 | get_result_iterator (void *cls, struct GNUNET_TIME_Absolute exp, | ||
172 | const struct GNUNET_HashCode * key, | ||
173 | const struct GNUNET_PeerIdentity *get_path, | ||
174 | unsigned int get_path_length, | ||
175 | const struct GNUNET_PeerIdentity *put_path, | ||
176 | unsigned int put_path_length, enum GNUNET_BLOCK_Type type, | ||
177 | size_t size, const void *data) | ||
178 | { | ||
179 | struct PeerGetContext *get_context = cls; | ||
180 | |||
181 | if (0 != | ||
182 | memcmp (&get_context->peer->hashPubKey, key, sizeof (struct GNUNET_HashCode))) | ||
183 | { | ||
184 | FPRINTF (stderr, "%s", "??\n"); | ||
185 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
186 | "Key returned is not the same key as was searched for!\n"); | ||
187 | GNUNET_SCHEDULER_cancel (die_task); | ||
188 | die_task = | ||
189 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
190 | "key mismatch in get response!\n"); | ||
191 | return; | ||
192 | } | ||
193 | if (get_context->retry_task != GNUNET_SCHEDULER_NO_TASK) | ||
194 | { | ||
195 | GNUNET_SCHEDULER_cancel (get_context->retry_task); | ||
196 | get_context->retry_task = GNUNET_SCHEDULER_NO_TASK; | ||
197 | } | ||
198 | |||
199 | if (get_context->peer == &peer2id) | ||
200 | { | ||
201 | get_context->peer = &peer1id; | ||
202 | get_context->dht_handle = peer2dht; | ||
203 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
204 | "Received first correct GET request response!\n"); | ||
205 | GNUNET_DHT_get_stop (get_context->get_handle); | ||
206 | GNUNET_SCHEDULER_add_now (&do_get, get_context); | ||
207 | } | ||
208 | else | ||
209 | { | ||
210 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
211 | "Received second correct GET request response!\n"); | ||
212 | GNUNET_SCHEDULER_cancel (die_task); | ||
213 | GNUNET_DHT_get_stop (get_context->get_handle); | ||
214 | die_task = GNUNET_SCHEDULER_add_now (&finish_testing, NULL); | ||
215 | } | ||
216 | |||
217 | } | ||
218 | |||
219 | static void | ||
220 | stop_retry_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
221 | |||
222 | |||
223 | static void | ||
224 | get_stop_finished (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
225 | { | ||
226 | struct PeerGetContext *get_context = cls; | ||
227 | |||
228 | if (get_context->get_attempts >= MAX_GET_ATTEMPTS) | ||
229 | { | ||
230 | FPRINTF (stderr, "%s", "?\n"); | ||
231 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
232 | "Too many attempts failed, ending test!\n", | ||
233 | get_context->get_attempts); | ||
234 | GNUNET_SCHEDULER_cancel (die_task); | ||
235 | die_task = | ||
236 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
237 | "GET attempt failed, ending test!\n"); | ||
238 | return; | ||
239 | } | ||
240 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
241 | "Get attempt %u failed, retrying request!\n", | ||
242 | get_context->get_attempts); | ||
243 | FPRINTF (stderr, "%s", "."); | ||
244 | get_context->get_attempts++; | ||
245 | get_context->retry_task = | ||
246 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
247 | (GNUNET_TIME_UNIT_SECONDS, 60), | ||
248 | &stop_retry_get, get_context); | ||
249 | get_context->get_handle = | ||
250 | GNUNET_DHT_get_start (get_context->dht_handle, | ||
251 | GNUNET_BLOCK_TYPE_DHT_HELLO, | ||
252 | &get_context->peer->hashPubKey, 1, | ||
253 | GNUNET_DHT_RO_NONE, NULL, 0, &get_result_iterator, | ||
254 | get_context); | ||
255 | } | ||
256 | |||
257 | |||
258 | static void | ||
259 | stop_retry_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
260 | { | ||
261 | struct PeerGetContext *get_context = cls; | ||
262 | |||
263 | get_context->retry_task = GNUNET_SCHEDULER_NO_TASK; | ||
264 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
265 | "Get attempt %u failed, canceling request!\n", | ||
266 | get_context->get_attempts); | ||
267 | GNUNET_DHT_get_stop (get_context->get_handle); | ||
268 | get_context->get_handle = NULL; | ||
269 | GNUNET_SCHEDULER_add_now (&get_stop_finished, get_context); | ||
270 | } | ||
271 | |||
272 | |||
273 | static void | ||
274 | do_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
275 | { | ||
276 | struct PeerGetContext *get_context = cls; | ||
277 | |||
278 | get_context->retry_task = | ||
279 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
280 | (GNUNET_TIME_UNIT_SECONDS, 10), | ||
281 | &stop_retry_get, get_context); | ||
282 | get_context->get_handle = | ||
283 | GNUNET_DHT_get_start (get_context->dht_handle, | ||
284 | GNUNET_BLOCK_TYPE_DHT_HELLO, | ||
285 | &get_context->peer->hashPubKey, 1, | ||
286 | GNUNET_DHT_RO_FIND_PEER, NULL, 0, | ||
287 | &get_result_iterator, get_context); | ||
288 | } | ||
289 | |||
290 | |||
291 | static void | ||
292 | topology_callback (void *cls, const struct GNUNET_PeerIdentity *first, | ||
293 | const struct GNUNET_PeerIdentity *second, uint32_t distance, | ||
294 | const struct GNUNET_CONFIGURATION_Handle *first_cfg, | ||
295 | const struct GNUNET_CONFIGURATION_Handle *second_cfg, | ||
296 | struct GNUNET_TESTING_Daemon *first_daemon, | ||
297 | struct GNUNET_TESTING_Daemon *second_daemon, | ||
298 | const char *emsg) | ||
299 | { | ||
300 | if (emsg == NULL) | ||
301 | { | ||
302 | total_connections++; | ||
303 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
304 | "connected peer %s to peer %s, distance %u\n", | ||
305 | first_daemon->shortname, second_daemon->shortname, distance); | ||
306 | } | ||
307 | else | ||
308 | { | ||
309 | failed_connections++; | ||
310 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
311 | "Failed to connect peer %s to peer %s with error :\n%s\n", | ||
312 | first_daemon->shortname, second_daemon->shortname, emsg); | ||
313 | } | ||
314 | |||
315 | if (total_connections == expected_connections) | ||
316 | { | ||
317 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
318 | "Created %d total connections, which is our target number! Starting next phase of testing.\n", | ||
319 | total_connections); | ||
320 | GNUNET_SCHEDULER_cancel (die_task); | ||
321 | die_task = | ||
322 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, | ||
323 | "Timeout trying to GET"); | ||
324 | |||
325 | curr_get_ctx.dht_handle = peer1dht; | ||
326 | curr_get_ctx.peer = &peer2id; | ||
327 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
328 | (GNUNET_TIME_UNIT_SECONDS, 2), &do_get, | ||
329 | &curr_get_ctx); | ||
330 | } | ||
331 | else if (total_connections + failed_connections == expected_connections) | ||
332 | { | ||
333 | GNUNET_SCHEDULER_cancel (die_task); | ||
334 | die_task = | ||
335 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
336 | "from topology_callback (too many failed connections)"); | ||
337 | } | ||
338 | } | ||
339 | |||
340 | |||
341 | static void | ||
342 | connect_topology (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
343 | { | ||
344 | expected_connections = -1; | ||
345 | if ((pg != NULL) && (peers_left == 0)) | ||
346 | expected_connections = | ||
347 | GNUNET_TESTING_connect_topology (pg, GNUNET_TESTING_TOPOLOGY_CLIQUE, | ||
348 | GNUNET_TESTING_TOPOLOGY_OPTION_ALL, | ||
349 | 0.0, TIMEOUT, 12, NULL, NULL); | ||
350 | |||
351 | GNUNET_SCHEDULER_cancel (die_task); | ||
352 | if (expected_connections == GNUNET_SYSERR) | ||
353 | die_task = | ||
354 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
355 | "from connect topology (bad return)"); | ||
356 | else | ||
357 | die_task = | ||
358 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, | ||
359 | "from connect topology (timeout)"); | ||
360 | } | ||
361 | |||
362 | |||
363 | static void | ||
364 | peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id, | ||
365 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
366 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
367 | { | ||
368 | if (emsg != NULL) | ||
369 | { | ||
370 | FPRINTF (stderr, "Failed to start daemon: `%s'\n", emsg); | ||
371 | return; | ||
372 | } | ||
373 | GNUNET_assert (id != NULL); | ||
374 | if (peers_left == num_peers) | ||
375 | { | ||
376 | memcpy (&peer1id, id, sizeof (struct GNUNET_PeerIdentity)); | ||
377 | peer1dht = GNUNET_DHT_connect (cfg, 100); | ||
378 | if (peer1dht == NULL) | ||
379 | { | ||
380 | GNUNET_SCHEDULER_cancel (die_task); | ||
381 | die_task = | ||
382 | GNUNET_SCHEDULER_add_now (&end_badly, "Failed to get dht handle!\n"); | ||
383 | } | ||
384 | } | ||
385 | else | ||
386 | { | ||
387 | memcpy (&peer2id, id, sizeof (struct GNUNET_PeerIdentity)); | ||
388 | peer2dht = GNUNET_DHT_connect (cfg, 100); | ||
389 | if (peer2dht == NULL) | ||
390 | { | ||
391 | GNUNET_SCHEDULER_cancel (die_task); | ||
392 | die_task = | ||
393 | GNUNET_SCHEDULER_add_now (&end_badly, "Failed to get dht handle!\n"); | ||
394 | } | ||
395 | } | ||
396 | |||
397 | |||
398 | peers_left--; | ||
399 | |||
400 | if (peers_left == 0) | ||
401 | { | ||
402 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
403 | "All %d daemons started, now connecting peers!\n", num_peers); | ||
404 | GNUNET_SCHEDULER_cancel (die_task); | ||
405 | /* Set up task in case topology creation doesn't finish | ||
406 | * within a reasonable amount of time */ | ||
407 | die_task = | ||
408 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, | ||
409 | "from peers_started_callback"); | ||
410 | |||
411 | GNUNET_SCHEDULER_add_now (&connect_topology, NULL); | ||
412 | ok = 0; | ||
413 | } | ||
414 | } | ||
415 | |||
416 | |||
417 | static void | ||
418 | run (void *cls, char *const *args, const char *cfgfile, | ||
419 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
420 | { | ||
421 | |||
422 | if (GNUNET_YES != | ||
423 | GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", | ||
424 | &test_directory)) | ||
425 | { | ||
426 | ok = 404; | ||
427 | return; | ||
428 | } | ||
429 | |||
430 | if (GNUNET_SYSERR == | ||
431 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing_old", "num_peers", | ||
432 | &num_peers)) | ||
433 | num_peers = DEFAULT_NUM_PEERS; | ||
434 | |||
435 | peers_left = num_peers; | ||
436 | total_gets = num_peers; | ||
437 | gets_succeeded = 0; | ||
438 | /* Set up a task to end testing if peer start fails */ | ||
439 | die_task = | ||
440 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, | ||
441 | "didn't start all daemons in reasonable amount of time!!!"); | ||
442 | |||
443 | pg = GNUNET_TESTING_daemons_start (cfg, num_peers, 10, num_peers, TIMEOUT, | ||
444 | NULL, NULL, &peers_started_callback, NULL, | ||
445 | &topology_callback, NULL, NULL); | ||
446 | |||
447 | } | ||
448 | |||
449 | static int | ||
450 | check () | ||
451 | { | ||
452 | int ret; | ||
453 | |||
454 | char *const argv[] = { "test-dht-twopeer", | ||
455 | "-c", | ||
456 | "test_dht_twopeer_data.conf", | ||
457 | NULL | ||
458 | }; | ||
459 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
460 | GNUNET_GETOPT_OPTION_END | ||
461 | }; | ||
462 | ret = | ||
463 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, | ||
464 | "test-dht-twopeer", "nohelp", options, &run, &ok); | ||
465 | if (ret != GNUNET_OK) | ||
466 | { | ||
467 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
468 | "`test-dht-twopeer': Failed with error code %d\n", ret); | ||
469 | } | ||
470 | return ok; | ||
471 | } | ||
472 | |||
473 | int | ||
474 | main (int argc, char *argv[]) | ||
475 | { | ||
476 | int ret; | ||
477 | |||
478 | GNUNET_log_setup ("test-dht-twopeer", | ||
479 | "WARNING", | ||
480 | NULL); | ||
481 | ret = check (); | ||
482 | /** | ||
483 | * Need to remove base directory, subdirectories taken care | ||
484 | * of by the testing framework. | ||
485 | */ | ||
486 | if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK) | ||
487 | { | ||
488 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
489 | "Failed to remove testing directory %s\n", test_directory); | ||
490 | } | ||
491 | return ret; | ||
492 | } | ||
493 | |||
494 | /* end of test_dht_twopeer.c */ | ||
diff --git a/src/dht/test_dht_twopeer_get_put.c b/src/dht/test_dht_twopeer_get_put.c deleted file mode 100644 index 3a27db21b..000000000 --- a/src/dht/test_dht_twopeer_get_put.c +++ /dev/null | |||
@@ -1,590 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009 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 | * @file dht/test_dht_twopeer_get_put.c | ||
22 | * @brief base testcase for testing DHT service with | ||
23 | * two running peers. | ||
24 | * | ||
25 | * This testcase starts peers using the GNUNET_TESTING_daemons_start | ||
26 | * function call. On peer start, connects to the peers DHT service | ||
27 | * by calling GNUNET_DHT_connected. Once notified about all peers | ||
28 | * being started (by the peers_started_callback function), calls | ||
29 | * GNUNET_TESTING_connect_topology, which connects the peers in a | ||
30 | * "straight line" topology. On notification that all peers have | ||
31 | * been properly connected, calls the do_get function which initiates | ||
32 | * a GNUNET_DHT_get from the *second* peer. Once the GNUNET_DHT_get | ||
33 | * function starts, runs the do_put function to insert data at the first peer. | ||
34 | * If the GET is successful, schedules finish_testing | ||
35 | * to stop the test and shut down peers. If GET is unsuccessful | ||
36 | * after GET_TIMEOUT seconds, prints an error message and shuts down | ||
37 | * the peers. | ||
38 | */ | ||
39 | #include "platform.h" | ||
40 | #include "gnunet_testing_lib.h" | ||
41 | #include "gnunet_core_service.h" | ||
42 | #include "gnunet_dht_service.h" | ||
43 | #include "block_dns.h" | ||
44 | #include "gnunet_signatures.h" | ||
45 | |||
46 | /* DEFINES */ | ||
47 | #define VERBOSE GNUNET_NO | ||
48 | |||
49 | /* Timeout for entire testcase */ | ||
50 | #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 40) | ||
51 | |||
52 | /* Timeout for waiting for replies to get requests */ | ||
53 | #define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30) | ||
54 | |||
55 | /* If number of peers not in config file, use this number */ | ||
56 | #define DEFAULT_NUM_PEERS 2 | ||
57 | |||
58 | #define DNS GNUNET_NO | ||
59 | |||
60 | /* Globals */ | ||
61 | |||
62 | /** | ||
63 | * Directory to store temp data in, defined in config file | ||
64 | */ | ||
65 | static char *test_directory; | ||
66 | |||
67 | /** | ||
68 | * Variable used to store the number of connections we should wait for. | ||
69 | */ | ||
70 | static unsigned int expected_connections; | ||
71 | |||
72 | /** | ||
73 | * Variable used to keep track of how many peers aren't yet started. | ||
74 | */ | ||
75 | static unsigned long long peers_left; | ||
76 | |||
77 | /** | ||
78 | * Handle to the set of all peers run for this test. | ||
79 | */ | ||
80 | static struct GNUNET_TESTING_PeerGroup *pg; | ||
81 | |||
82 | /** | ||
83 | * Global handle we will use for GET requests. | ||
84 | */ | ||
85 | struct GNUNET_DHT_GetHandle *global_get_handle; | ||
86 | |||
87 | |||
88 | /** | ||
89 | * Total number of peers to run, set based on config file. | ||
90 | */ | ||
91 | static unsigned long long num_peers; | ||
92 | |||
93 | /** | ||
94 | * Global used to count how many connections we have currently | ||
95 | * been notified about (how many times has topology_callback been called | ||
96 | * with success?) | ||
97 | */ | ||
98 | static unsigned int total_connections; | ||
99 | |||
100 | /** | ||
101 | * Global used to count how many failed connections we have | ||
102 | * been notified about (how many times has topology_callback | ||
103 | * been called with failure?) | ||
104 | */ | ||
105 | static unsigned int failed_connections; | ||
106 | |||
107 | /* Task handle to use to schedule test failure */ | ||
108 | GNUNET_SCHEDULER_TaskIdentifier die_task; | ||
109 | |||
110 | /* Global return value (0 for success, anything else for failure) */ | ||
111 | static int ok; | ||
112 | |||
113 | #if DNS | ||
114 | struct GNUNET_DNS_Record data; | ||
115 | #endif | ||
116 | |||
117 | /** | ||
118 | * Peer identity of the first peer started. | ||
119 | */ | ||
120 | static struct GNUNET_PeerIdentity peer1id; | ||
121 | |||
122 | /** | ||
123 | * Peer identity of the second peer started. | ||
124 | */ | ||
125 | static struct GNUNET_PeerIdentity peer2id; | ||
126 | |||
127 | /** | ||
128 | * Handle to the first peers DHT service (via the API) | ||
129 | */ | ||
130 | static struct GNUNET_DHT_Handle *peer1dht; | ||
131 | |||
132 | /** | ||
133 | * Handle to the second peers DHT service (via the API) | ||
134 | */ | ||
135 | static struct GNUNET_DHT_Handle *peer2dht; | ||
136 | |||
137 | static void | ||
138 | do_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
139 | |||
140 | /** | ||
141 | * Check whether peers successfully shut down. | ||
142 | */ | ||
143 | void | ||
144 | shutdown_callback (void *cls, const char *emsg) | ||
145 | { | ||
146 | if (emsg != NULL) | ||
147 | { | ||
148 | if (ok == 0) | ||
149 | ok = 2; | ||
150 | } | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * Function scheduled to be run on the successful completion of this | ||
155 | * testcase. Specifically, called when our get request completes. | ||
156 | */ | ||
157 | static void | ||
158 | finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
159 | { | ||
160 | GNUNET_assert (pg != NULL); | ||
161 | GNUNET_assert (peer1dht != NULL); | ||
162 | GNUNET_assert (peer2dht != NULL); | ||
163 | GNUNET_DHT_disconnect (peer1dht); | ||
164 | GNUNET_DHT_disconnect (peer2dht); | ||
165 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
166 | ok = 0; | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut | ||
171 | * down the peers without freeing memory associated with GET request. | ||
172 | */ | ||
173 | static void | ||
174 | end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
175 | { | ||
176 | if (peer1dht != NULL) | ||
177 | GNUNET_DHT_disconnect (peer1dht); | ||
178 | |||
179 | if (peer2dht != NULL) | ||
180 | GNUNET_DHT_disconnect (peer2dht); | ||
181 | |||
182 | if (pg != NULL) | ||
183 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * Check if the get_handle is being used, if so stop the request. Either | ||
188 | * way, schedule the end_badly_cont function which actually shuts down the | ||
189 | * test. | ||
190 | */ | ||
191 | static void | ||
192 | end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
193 | { | ||
194 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failing test with error: `%s'!\n", | ||
195 | (char *) cls); | ||
196 | if (global_get_handle != NULL) | ||
197 | { | ||
198 | GNUNET_DHT_get_stop (global_get_handle); | ||
199 | global_get_handle = NULL; | ||
200 | } | ||
201 | GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL); | ||
202 | ok = 1; | ||
203 | } | ||
204 | |||
205 | /** | ||
206 | * Iterator called if the GET request initiated returns a response. | ||
207 | * | ||
208 | * @param cls closure | ||
209 | * @param exp when will this value expire | ||
210 | * @param key key of the result | ||
211 | * @param type type of the result | ||
212 | * @param size number of bytes in data | ||
213 | * @param data pointer to the result data | ||
214 | */ | ||
215 | void | ||
216 | get_result_iterator (void *cls, struct GNUNET_TIME_Absolute exp, | ||
217 | const struct GNUNET_HashCode * key, | ||
218 | const struct GNUNET_PeerIdentity *get_path, | ||
219 | unsigned int get_path_size, | ||
220 | const struct GNUNET_PeerIdentity *put_path, | ||
221 | unsigned int put_path_size, enum GNUNET_BLOCK_Type type, | ||
222 | size_t size, const void *result_data) | ||
223 | { | ||
224 | struct GNUNET_HashCode original_key; /* Key data was stored data under */ | ||
225 | char original_data[4]; /* Made up data that was stored */ | ||
226 | |||
227 | memset (&original_key, 42, sizeof (struct GNUNET_HashCode)); /* Set the key to what it was set to previously */ | ||
228 | memset (original_data, 43, sizeof (original_data)); | ||
229 | |||
230 | #if DNS | ||
231 | if ((sizeof (original_data) != size) || | ||
232 | (0 != memcmp (&data.service_descriptor, key, sizeof (struct GNUNET_HashCode))) || | ||
233 | (0 != memcmp ((char *) &data, result_data, sizeof (original_data)))) | ||
234 | { | ||
235 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
236 | "Key or data is not the same as was inserted!\n"); | ||
237 | GNUNET_SCHEDULER_cancel (die_task); | ||
238 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
239 | "key or data mismatch in get response!\n"); | ||
240 | return; | ||
241 | } | ||
242 | #else | ||
243 | if ((sizeof (original_data) != size) || | ||
244 | (0 != memcmp (&original_key, key, sizeof (struct GNUNET_HashCode))) || | ||
245 | (0 != memcmp (original_data, result_data, sizeof (original_data)))) | ||
246 | { | ||
247 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
248 | "Key or data is not the same as was inserted!\n"); | ||
249 | GNUNET_SCHEDULER_cancel (die_task); | ||
250 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
251 | "key or data mismatch in get response!\n"); | ||
252 | return; | ||
253 | } | ||
254 | #endif | ||
255 | |||
256 | GNUNET_SCHEDULER_cancel (die_task); | ||
257 | GNUNET_DHT_get_stop (global_get_handle); | ||
258 | GNUNET_SCHEDULER_add_now (&finish_testing, NULL); | ||
259 | } | ||
260 | |||
261 | /** | ||
262 | * Start the GET request for the same key/data that was inserted. | ||
263 | */ | ||
264 | static void | ||
265 | do_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
266 | { | ||
267 | struct GNUNET_HashCode key; /* Key for data lookup */ | ||
268 | |||
269 | #if DNS | ||
270 | memcpy (&key, &data.service_descriptor, sizeof (struct GNUNET_HashCode)); | ||
271 | #else | ||
272 | memset (&key, 42, sizeof (struct GNUNET_HashCode)); /* Set the key to the same thing as when data was inserted */ | ||
273 | #endif | ||
274 | global_get_handle = | ||
275 | GNUNET_DHT_get_start (peer2dht, | ||
276 | #if DNS | ||
277 | GNUNET_BLOCK_TYPE_DNS, | ||
278 | #else | ||
279 | GNUNET_BLOCK_TYPE_TEST, | ||
280 | #endif | ||
281 | &key, 1, GNUNET_DHT_RO_NONE, NULL, 0, | ||
282 | &get_result_iterator, NULL); | ||
283 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
284 | (GNUNET_TIME_UNIT_SECONDS, 10), &do_put, NULL); | ||
285 | } | ||
286 | |||
287 | /** | ||
288 | * Called when the PUT request has been transmitted to the DHT service. | ||
289 | * Schedule the GET request for some time in the future. | ||
290 | */ | ||
291 | static void | ||
292 | put_finished (void *cls, int success) | ||
293 | { | ||
294 | GNUNET_SCHEDULER_cancel (die_task); | ||
295 | die_task = | ||
296 | GNUNET_SCHEDULER_add_delayed (GET_TIMEOUT, &end_badly, | ||
297 | "waiting for get response (data not found)"); | ||
298 | } | ||
299 | |||
300 | |||
301 | #if !DNS | ||
302 | /** | ||
303 | * Set up some data, and call API PUT function | ||
304 | */ | ||
305 | static void | ||
306 | do_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
307 | { | ||
308 | struct GNUNET_HashCode key; /* Made up key to store data under */ | ||
309 | char data[4]; /* Made up data to store */ | ||
310 | |||
311 | memset (&key, 42, sizeof (struct GNUNET_HashCode)); /* Set the key to something simple so we can issue GET request */ | ||
312 | memset (data, 43, sizeof (data)); | ||
313 | |||
314 | /* Insert the data at the first peer */ | ||
315 | GNUNET_DHT_put (peer1dht, &key, 1, GNUNET_DHT_RO_NONE, GNUNET_BLOCK_TYPE_TEST, | ||
316 | sizeof (data), data, GNUNET_TIME_UNIT_FOREVER_ABS, | ||
317 | GNUNET_TIME_UNIT_FOREVER_REL, &put_finished, NULL); | ||
318 | } | ||
319 | #else | ||
320 | |||
321 | /** | ||
322 | * Set up some data, and call API PUT function | ||
323 | */ | ||
324 | static void | ||
325 | do_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
326 | { | ||
327 | char *name = "philipptoelke.gnunet."; | ||
328 | size_t size = sizeof (struct GNUNET_DNS_Record); | ||
329 | |||
330 | memset (&data, 0, size); | ||
331 | |||
332 | data.purpose.size = htonl (size - sizeof (struct GNUNET_CRYPTO_RsaSignature)); | ||
333 | data.purpose.purpose = GNUNET_SIGNATURE_PURPOSE_DNS_RECORD; | ||
334 | |||
335 | GNUNET_CRYPTO_hash (name, strlen (name) + 1, &data.service_descriptor); | ||
336 | |||
337 | data.service_type = htonl (GNUNET_DNS_SERVICE_TYPE_UDP); | ||
338 | data.ports = htons (69); | ||
339 | |||
340 | char *keyfile; | ||
341 | |||
342 | GNUNET_asprintf (&keyfile, "/tmp/test_dns_data_key"); | ||
343 | struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key = | ||
344 | GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); | ||
345 | GNUNET_free (keyfile); | ||
346 | GNUNET_assert (my_private_key != NULL); | ||
347 | |||
348 | GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &data.peer); | ||
349 | |||
350 | data.expiration_time = | ||
351 | GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS); | ||
352 | |||
353 | /* Sign the block */ | ||
354 | if (GNUNET_OK != | ||
355 | GNUNET_CRYPTO_rsa_sign (my_private_key, &data.purpose, &data.signature)) | ||
356 | { | ||
357 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not sign DNS_Record\n"); | ||
358 | return; | ||
359 | } | ||
360 | GNUNET_CRYPTO_rsa_key_free (my_private_key); | ||
361 | |||
362 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting with key %08x\n", | ||
363 | *((unsigned int *) &data.service_descriptor)); | ||
364 | |||
365 | GNUNET_DHT_put (peer1dht, &data.service_descriptor, DEFAULT_PUT_REPLICATION, | ||
366 | GNUNET_DHT_RO_NONE, GNUNET_BLOCK_TYPE_DNS, size, | ||
367 | (char *) &data, | ||
368 | GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS), | ||
369 | GNUNET_TIME_UNIT_MINUTES, &put_finished, NULL); | ||
370 | } | ||
371 | #endif | ||
372 | |||
373 | /** | ||
374 | * This function is called whenever a connection attempt is finished between two of | ||
375 | * the started peers (started with GNUNET_TESTING_daemons_start). The total | ||
376 | * number of times this function is called should equal the number returned | ||
377 | * from the GNUNET_TESTING_connect_topology call. | ||
378 | * | ||
379 | * The emsg variable is NULL on success (peers connected), and non-NULL on | ||
380 | * failure (peers failed to connect). | ||
381 | */ | ||
382 | void | ||
383 | topology_callback (void *cls, const struct GNUNET_PeerIdentity *first, | ||
384 | const struct GNUNET_PeerIdentity *second, uint32_t distance, | ||
385 | const struct GNUNET_CONFIGURATION_Handle *first_cfg, | ||
386 | const struct GNUNET_CONFIGURATION_Handle *second_cfg, | ||
387 | struct GNUNET_TESTING_Daemon *first_daemon, | ||
388 | struct GNUNET_TESTING_Daemon *second_daemon, | ||
389 | const char *emsg) | ||
390 | { | ||
391 | if (emsg == NULL) | ||
392 | { | ||
393 | total_connections++; | ||
394 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
395 | "connected peer %s to peer %s, distance %u\n", | ||
396 | first_daemon->shortname, second_daemon->shortname, distance); | ||
397 | } | ||
398 | else | ||
399 | { | ||
400 | failed_connections++; | ||
401 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
402 | "Failed to connect peer %s to peer %s with error :\n%s\n", | ||
403 | first_daemon->shortname, second_daemon->shortname, emsg); | ||
404 | } | ||
405 | |||
406 | if (total_connections == expected_connections) | ||
407 | { | ||
408 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
409 | "Created %d total connections, which is our target number! Starting next phase of testing.\n", | ||
410 | total_connections); | ||
411 | GNUNET_SCHEDULER_cancel (die_task); | ||
412 | die_task = | ||
413 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, "from test gets"); | ||
414 | |||
415 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
416 | (GNUNET_TIME_UNIT_SECONDS, 2), &do_get, NULL); | ||
417 | } | ||
418 | else if (total_connections + failed_connections == expected_connections) | ||
419 | { | ||
420 | GNUNET_SCHEDULER_cancel (die_task); | ||
421 | die_task = | ||
422 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
423 | "from topology_callback (too many failed connections)"); | ||
424 | } | ||
425 | } | ||
426 | |||
427 | |||
428 | /** | ||
429 | * Callback which is called whenever a peer is started (as a result of the | ||
430 | * GNUNET_TESTING_daemons_start call. | ||
431 | * | ||
432 | * @param cls closure argument given to GNUNET_TESTING_daemons_start | ||
433 | * @param id the GNUNET_PeerIdentity of the started peer | ||
434 | * @param cfg the configuration for this specific peer (needed to connect | ||
435 | * to the DHT) | ||
436 | * @param d the handle to the daemon started | ||
437 | * @param emsg NULL if peer started, non-NULL on error | ||
438 | */ | ||
439 | static void | ||
440 | peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id, | ||
441 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
442 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
443 | { | ||
444 | if (emsg != NULL) | ||
445 | { | ||
446 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
447 | "Failed to start daemon with error: `%s'\n", emsg); | ||
448 | return; | ||
449 | } | ||
450 | GNUNET_assert (id != NULL); | ||
451 | |||
452 | /* This is the first peer started */ | ||
453 | if (peers_left == num_peers) | ||
454 | { | ||
455 | memcpy (&peer1id, id, sizeof (struct GNUNET_PeerIdentity)); /* Save the peer id */ | ||
456 | peer1dht = GNUNET_DHT_connect (cfg, 100); /* Connect to the first peers DHT service */ | ||
457 | if (peer1dht == NULL) /* If DHT connect failed */ | ||
458 | { | ||
459 | GNUNET_SCHEDULER_cancel (die_task); | ||
460 | GNUNET_SCHEDULER_add_now (&end_badly, "Failed to get dht handle!\n"); | ||
461 | } | ||
462 | } | ||
463 | else /* This is the second peer started */ | ||
464 | { | ||
465 | memcpy (&peer2id, id, sizeof (struct GNUNET_PeerIdentity)); /* Same as for first peer... */ | ||
466 | peer2dht = GNUNET_DHT_connect (cfg, 100); | ||
467 | if (peer2dht == NULL) | ||
468 | { | ||
469 | GNUNET_SCHEDULER_cancel (die_task); | ||
470 | GNUNET_SCHEDULER_add_now (&end_badly, "Failed to get dht handle!\n"); | ||
471 | } | ||
472 | } | ||
473 | |||
474 | /* Decrement number of peers left to start */ | ||
475 | peers_left--; | ||
476 | |||
477 | if (peers_left == 0) /* Indicates all peers started */ | ||
478 | { | ||
479 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
480 | "All %d daemons started, now connecting peers!\n", num_peers); | ||
481 | expected_connections = -1; | ||
482 | if ((pg != NULL)) /* Sanity check */ | ||
483 | { | ||
484 | /* Connect peers in a "straight line" topology, return the number of expected connections */ | ||
485 | expected_connections = | ||
486 | GNUNET_TESTING_connect_topology (pg, GNUNET_TESTING_TOPOLOGY_LINE, | ||
487 | GNUNET_TESTING_TOPOLOGY_OPTION_ALL, | ||
488 | 0.0, TIMEOUT, 12, NULL, NULL); | ||
489 | } | ||
490 | |||
491 | /* Cancel current timeout fail task */ | ||
492 | GNUNET_SCHEDULER_cancel (die_task); | ||
493 | if (expected_connections == GNUNET_SYSERR) /* Some error happened */ | ||
494 | die_task = | ||
495 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
496 | "from connect topology (bad return)"); | ||
497 | |||
498 | /* Schedule timeout on failure task */ | ||
499 | die_task = | ||
500 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, | ||
501 | "from connect topology (timeout)"); | ||
502 | ok = 0; | ||
503 | } | ||
504 | } | ||
505 | |||
506 | static void | ||
507 | run (void *cls, char *const *args, const char *cfgfile, | ||
508 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
509 | { | ||
510 | |||
511 | /* Get path from configuration file */ | ||
512 | if (GNUNET_YES != | ||
513 | GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", | ||
514 | &test_directory)) | ||
515 | { | ||
516 | ok = 404; | ||
517 | return; | ||
518 | } | ||
519 | |||
520 | /* Get number of peers to start from configuration (should be two) */ | ||
521 | if (GNUNET_SYSERR == | ||
522 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing_old", "num_peers", | ||
523 | &num_peers)) | ||
524 | num_peers = DEFAULT_NUM_PEERS; | ||
525 | |||
526 | /* Set peers_left so we know when all peers started */ | ||
527 | peers_left = num_peers; | ||
528 | |||
529 | /* Set up a task to end testing if peer start fails */ | ||
530 | die_task = | ||
531 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, | ||
532 | "didn't start all daemons in reasonable amount of time!!!"); | ||
533 | |||
534 | /* Start num_peers peers, call peers_started_callback on peer start, topology_callback on peer connect */ | ||
535 | /* Read the API documentation for other parameters! */ | ||
536 | pg = GNUNET_TESTING_daemons_start (cfg, num_peers, 2, 2, TIMEOUT, NULL, NULL, | ||
537 | &peers_started_callback, NULL, | ||
538 | &topology_callback, NULL, NULL); | ||
539 | |||
540 | } | ||
541 | |||
542 | static int | ||
543 | check () | ||
544 | { | ||
545 | int ret; | ||
546 | |||
547 | /* Arguments for GNUNET_PROGRAM_run */ | ||
548 | char *const argv[] = { "test-dht-twopeer-get-put", /* Name to give running binary */ | ||
549 | "-c", | ||
550 | "test_dht_twopeer_data.conf", /* Config file to use */ | ||
551 | NULL | ||
552 | }; | ||
553 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
554 | GNUNET_GETOPT_OPTION_END | ||
555 | }; | ||
556 | /* Run the run function as a new program */ | ||
557 | ret = | ||
558 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, | ||
559 | "test-dht-twopeer-get-put", "nohelp", options, &run, | ||
560 | &ok); | ||
561 | if (ret != GNUNET_OK) | ||
562 | { | ||
563 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
564 | "`test-dht-twopeer': Failed with error code %d\n", ret); | ||
565 | } | ||
566 | return ok; | ||
567 | } | ||
568 | |||
569 | int | ||
570 | main (int argc, char *argv[]) | ||
571 | { | ||
572 | int ret; | ||
573 | |||
574 | GNUNET_log_setup ("test-dht-twopeer", | ||
575 | "WARNING", | ||
576 | NULL); | ||
577 | ret = check (); | ||
578 | /** | ||
579 | * Need to remove base directory, subdirectories taken care | ||
580 | * of by the testing framework. | ||
581 | */ | ||
582 | if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK) | ||
583 | { | ||
584 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
585 | "Failed to remove testing directory %s\n", test_directory); | ||
586 | } | ||
587 | return ret; | ||
588 | } | ||
589 | |||
590 | /* end of test_dht_twopeer_get_put.c */ | ||
diff --git a/src/dht/test_dht_twopeer_path_tracking.c b/src/dht/test_dht_twopeer_path_tracking.c deleted file mode 100644 index 86086b806..000000000 --- a/src/dht/test_dht_twopeer_path_tracking.c +++ /dev/null | |||
@@ -1,522 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009 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 | * @file dht/test_dht_twopeer_path_tracking.c | ||
22 | * @brief testcase for testing DHT service with | ||
23 | * two running peers, logging the path of the dht requests. | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_testing_lib.h" | ||
27 | #include "gnunet_core_service.h" | ||
28 | #include "gnunet_dht_service.h" | ||
29 | |||
30 | /* DEFINES */ | ||
31 | #define VERBOSE GNUNET_NO | ||
32 | |||
33 | /* Timeout for entire testcase */ | ||
34 | #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5) | ||
35 | |||
36 | /* Timeout for waiting for replies to get requests */ | ||
37 | #define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30) | ||
38 | |||
39 | /* If number of peers not in config file, use this number */ | ||
40 | #define DEFAULT_NUM_PEERS 2 | ||
41 | |||
42 | /* Globals */ | ||
43 | |||
44 | /** | ||
45 | * Directory to store temp data in, defined in config file | ||
46 | */ | ||
47 | static char *test_directory; | ||
48 | |||
49 | /** | ||
50 | * Variable used to store the number of connections we should wait for. | ||
51 | */ | ||
52 | static unsigned int expected_connections; | ||
53 | |||
54 | /** | ||
55 | * Variable used to keep track of how many peers aren't yet started. | ||
56 | */ | ||
57 | static unsigned long long peers_left; | ||
58 | |||
59 | /** | ||
60 | * Handle to the set of all peers run for this test. | ||
61 | */ | ||
62 | static struct GNUNET_TESTING_PeerGroup *pg; | ||
63 | |||
64 | /** | ||
65 | * Global handle we will use for GET requests. | ||
66 | */ | ||
67 | struct GNUNET_DHT_GetHandle *global_get_handle; | ||
68 | |||
69 | |||
70 | /** | ||
71 | * Total number of peers to run, set based on config file. | ||
72 | */ | ||
73 | static unsigned long long num_peers; | ||
74 | |||
75 | /** | ||
76 | * Global used to count how many connections we have currently | ||
77 | * been notified about (how many times has topology_callback been called | ||
78 | * with success?) | ||
79 | */ | ||
80 | static unsigned int total_connections; | ||
81 | |||
82 | /** | ||
83 | * Global used to count how many failed connections we have | ||
84 | * been notified about (how many times has topology_callback | ||
85 | * been called with failure?) | ||
86 | */ | ||
87 | static unsigned int failed_connections; | ||
88 | |||
89 | /** | ||
90 | * Task handle to use to schedule test failure | ||
91 | */ | ||
92 | GNUNET_SCHEDULER_TaskIdentifier die_task; | ||
93 | |||
94 | /** | ||
95 | * Global return value (0 for success, anything else for failure) | ||
96 | */ | ||
97 | static int ok; | ||
98 | |||
99 | /** | ||
100 | * Peer identity of the first peer started. | ||
101 | */ | ||
102 | static struct GNUNET_PeerIdentity peer1id; | ||
103 | |||
104 | /** | ||
105 | * Peer identity of the second peer started. | ||
106 | */ | ||
107 | static struct GNUNET_PeerIdentity peer2id; | ||
108 | |||
109 | /** | ||
110 | * Handle to the first peers DHT service (via the API) | ||
111 | */ | ||
112 | static struct GNUNET_DHT_Handle *peer1dht; | ||
113 | |||
114 | /** | ||
115 | * Handle to the second peers DHT service (via the API) | ||
116 | */ | ||
117 | static struct GNUNET_DHT_Handle *peer2dht; | ||
118 | |||
119 | /** | ||
120 | * Check whether peers successfully shut down. | ||
121 | */ | ||
122 | void | ||
123 | shutdown_callback (void *cls, const char *emsg) | ||
124 | { | ||
125 | if (emsg != NULL) | ||
126 | { | ||
127 | if (ok == 0) | ||
128 | ok = 2; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * Function scheduled to be run on the successful completion of this | ||
134 | * testcase. Specifically, called when our get request completes. | ||
135 | */ | ||
136 | static void | ||
137 | finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
138 | { | ||
139 | GNUNET_assert (pg != NULL); | ||
140 | GNUNET_assert (peer1dht != NULL); | ||
141 | GNUNET_assert (peer2dht != NULL); | ||
142 | GNUNET_DHT_disconnect (peer1dht); | ||
143 | GNUNET_DHT_disconnect (peer2dht); | ||
144 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
145 | ok = 0; | ||
146 | } | ||
147 | |||
148 | /** | ||
149 | * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut | ||
150 | * down the peers without freeing memory associated with GET request. | ||
151 | */ | ||
152 | static void | ||
153 | end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
154 | { | ||
155 | if (peer1dht != NULL) | ||
156 | GNUNET_DHT_disconnect (peer1dht); | ||
157 | |||
158 | if (peer2dht != NULL) | ||
159 | GNUNET_DHT_disconnect (peer2dht); | ||
160 | |||
161 | if (pg != NULL) | ||
162 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * Check if the get_handle is being used, if so stop the request. Either | ||
167 | * way, schedule the end_badly_cont function which actually shuts down the | ||
168 | * test. | ||
169 | */ | ||
170 | static void | ||
171 | end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
172 | { | ||
173 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failing test with error: `%s'!\n", | ||
174 | (char *) cls); | ||
175 | if (global_get_handle != NULL) | ||
176 | { | ||
177 | GNUNET_DHT_get_stop (global_get_handle); | ||
178 | global_get_handle = NULL; | ||
179 | } | ||
180 | GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL); | ||
181 | ok = 1; | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * Iterator called if the GET request initiated returns a response. | ||
186 | * | ||
187 | * @param cls closure | ||
188 | * @param exp when will this value expire | ||
189 | * @param key key of the result | ||
190 | * @param type type of the result | ||
191 | * @param size number of bytes in data | ||
192 | * @param data pointer to the result data | ||
193 | */ | ||
194 | static void | ||
195 | get_result_iterator (void *cls, struct GNUNET_TIME_Absolute exp, | ||
196 | const struct GNUNET_HashCode * key, | ||
197 | const struct GNUNET_PeerIdentity *get_path, | ||
198 | unsigned int get_path_length, | ||
199 | const struct GNUNET_PeerIdentity *put_path, | ||
200 | unsigned int put_path_length, enum GNUNET_BLOCK_Type type, | ||
201 | size_t size, const void *data) | ||
202 | { | ||
203 | struct GNUNET_HashCode original_key; /* Key data was stored data under */ | ||
204 | char original_data[4]; /* Made up data that was stored */ | ||
205 | |||
206 | memset (&original_key, 42, sizeof (struct GNUNET_HashCode)); /* Set the key to what it was set to previously */ | ||
207 | memset (original_data, 43, sizeof (original_data)); | ||
208 | #if VERBOSE | ||
209 | unsigned int i; | ||
210 | #endif | ||
211 | |||
212 | if ((0 != memcmp (&original_key, key, sizeof (struct GNUNET_HashCode))) || | ||
213 | (0 != memcmp (original_data, data, sizeof (original_data)))) | ||
214 | { | ||
215 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
216 | "Key or data is not the same as was inserted!\n"); | ||
217 | GNUNET_SCHEDULER_cancel (die_task); | ||
218 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
219 | "key or data mismatch in get response!\n"); | ||
220 | return; | ||
221 | } | ||
222 | |||
223 | #if VERBOSE | ||
224 | if (put_path != NULL) | ||
225 | { | ||
226 | FPRINTF (stderr, "%s", "PUT Path: "); | ||
227 | for (i = 0; i < put_path_length; i++) | ||
228 | FPRINTF (stderr, "%s%s", i == 0 ? "" : "->", GNUNET_i2s (&put_path[i])); | ||
229 | FPRINTF (stderr, "%s", "\n"); | ||
230 | } | ||
231 | if (get_path != NULL) | ||
232 | { | ||
233 | FPRINTF (stderr, "%s", "GET Path: "); | ||
234 | for (i = 0; i < get_path_length; i++) | ||
235 | FPRINTF (stderr, "%s%s", i == 0 ? "" : "->", GNUNET_i2s (&get_path[i])); | ||
236 | FPRINTF (stderr, "%s", "\n"); | ||
237 | } | ||
238 | #endif | ||
239 | |||
240 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received correct GET response!\n"); | ||
241 | GNUNET_SCHEDULER_cancel (die_task); | ||
242 | GNUNET_DHT_get_stop (global_get_handle); | ||
243 | GNUNET_SCHEDULER_add_now (&finish_testing, NULL); | ||
244 | } | ||
245 | |||
246 | |||
247 | /** | ||
248 | * Called when the PUT request has been transmitted to the DHT service. | ||
249 | * Schedule the GET request for some time in the future. | ||
250 | */ | ||
251 | static void | ||
252 | put_finished (void *cls, int success) | ||
253 | { | ||
254 | struct GNUNET_HashCode key; /* Key for data lookup */ | ||
255 | |||
256 | GNUNET_SCHEDULER_cancel (die_task); | ||
257 | die_task = | ||
258 | GNUNET_SCHEDULER_add_delayed (GET_TIMEOUT, &end_badly, | ||
259 | "waiting for get response (data not found)"); | ||
260 | memset (&key, 42, sizeof (struct GNUNET_HashCode)); /* Set the key to the same thing as when data was inserted */ | ||
261 | global_get_handle = | ||
262 | GNUNET_DHT_get_start (peer2dht, | ||
263 | GNUNET_BLOCK_TYPE_TEST, &key, 1, | ||
264 | GNUNET_DHT_RO_RECORD_ROUTE, NULL, 0, | ||
265 | &get_result_iterator, NULL); | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * Set up some data, and call API PUT function | ||
270 | */ | ||
271 | static void | ||
272 | do_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
273 | { | ||
274 | struct GNUNET_HashCode key; /* Made up key to store data under */ | ||
275 | char data[4]; /* Made up data to store */ | ||
276 | |||
277 | memset (&key, 42, sizeof (struct GNUNET_HashCode)); /* Set the key to something simple so we can issue GET request */ | ||
278 | memset (data, 43, sizeof (data)); | ||
279 | |||
280 | /* Insert the data at the first peer */ | ||
281 | GNUNET_DHT_put (peer1dht, &key, 1, GNUNET_DHT_RO_RECORD_ROUTE, | ||
282 | GNUNET_BLOCK_TYPE_TEST, sizeof (data), data, | ||
283 | GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_TIME_UNIT_FOREVER_REL, | ||
284 | &put_finished, NULL); | ||
285 | } | ||
286 | |||
287 | /** | ||
288 | * This function is called whenever a connection attempt is finished between two of | ||
289 | * the started peers (started with GNUNET_TESTING_daemons_start). The total | ||
290 | * number of times this function is called should equal the number returned | ||
291 | * from the GNUNET_TESTING_connect_topology call. | ||
292 | * | ||
293 | * The emsg variable is NULL on success (peers connected), and non-NULL on | ||
294 | * failure (peers failed to connect). | ||
295 | */ | ||
296 | static void | ||
297 | topology_callback (void *cls, const struct GNUNET_PeerIdentity *first, | ||
298 | const struct GNUNET_PeerIdentity *second, uint32_t distance, | ||
299 | const struct GNUNET_CONFIGURATION_Handle *first_cfg, | ||
300 | const struct GNUNET_CONFIGURATION_Handle *second_cfg, | ||
301 | struct GNUNET_TESTING_Daemon *first_daemon, | ||
302 | struct GNUNET_TESTING_Daemon *second_daemon, | ||
303 | const char *emsg) | ||
304 | { | ||
305 | if (emsg == NULL) | ||
306 | { | ||
307 | total_connections++; | ||
308 | #if VERBOSE | ||
309 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
310 | "connected peer %s to peer %s, distance %u\n", | ||
311 | first_daemon->shortname, second_daemon->shortname, distance); | ||
312 | #endif | ||
313 | } | ||
314 | #if VERBOSE | ||
315 | else | ||
316 | { | ||
317 | failed_connections++; | ||
318 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
319 | "Failed to connect peer %s to peer %s with error :\n%s\n", | ||
320 | first_daemon->shortname, second_daemon->shortname, emsg); | ||
321 | } | ||
322 | #endif | ||
323 | |||
324 | if (total_connections == expected_connections) | ||
325 | { | ||
326 | #if VERBOSE | ||
327 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
328 | "Created %d total connections, which is our target number! Starting next phase of testing.\n", | ||
329 | total_connections); | ||
330 | #endif | ||
331 | GNUNET_SCHEDULER_cancel (die_task); | ||
332 | die_task = | ||
333 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, "from test gets"); | ||
334 | |||
335 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
336 | (GNUNET_TIME_UNIT_SECONDS, 2), &do_put, NULL); | ||
337 | } | ||
338 | else if (total_connections + failed_connections == expected_connections) | ||
339 | { | ||
340 | GNUNET_SCHEDULER_cancel (die_task); | ||
341 | die_task = | ||
342 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
343 | "from topology_callback (too many failed connections)"); | ||
344 | } | ||
345 | } | ||
346 | |||
347 | |||
348 | /** | ||
349 | * Callback which is called whenever a peer is started (as a result of the | ||
350 | * GNUNET_TESTING_daemons_start call. | ||
351 | * | ||
352 | * @param cls closure argument given to GNUNET_TESTING_daemons_start | ||
353 | * @param id the GNUNET_PeerIdentity of the started peer | ||
354 | * @param cfg the configuration for this specific peer (needed to connect | ||
355 | * to the DHT) | ||
356 | * @param d the handle to the daemon started | ||
357 | * @param emsg NULL if peer started, non-NULL on error | ||
358 | */ | ||
359 | static void | ||
360 | peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id, | ||
361 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
362 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
363 | { | ||
364 | if (emsg != NULL) | ||
365 | { | ||
366 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
367 | "Failed to start daemon with error: `%s'\n", emsg); | ||
368 | return; | ||
369 | } | ||
370 | GNUNET_assert (id != NULL); | ||
371 | |||
372 | /* This is the first peer started */ | ||
373 | if (peers_left == num_peers) | ||
374 | { | ||
375 | memcpy (&peer1id, id, sizeof (struct GNUNET_PeerIdentity)); /* Save the peer id */ | ||
376 | peer1dht = GNUNET_DHT_connect (cfg, 100); /* Connect to the first peers DHT service */ | ||
377 | if (peer1dht == NULL) /* If DHT connect failed */ | ||
378 | { | ||
379 | GNUNET_SCHEDULER_cancel (die_task); | ||
380 | GNUNET_SCHEDULER_add_now (&end_badly, "Failed to get dht handle!\n"); | ||
381 | } | ||
382 | } | ||
383 | else /* This is the second peer started */ | ||
384 | { | ||
385 | memcpy (&peer2id, id, sizeof (struct GNUNET_PeerIdentity)); /* Same as for first peer... */ | ||
386 | peer2dht = GNUNET_DHT_connect (cfg, 100); | ||
387 | if (peer2dht == NULL) | ||
388 | { | ||
389 | GNUNET_SCHEDULER_cancel (die_task); | ||
390 | GNUNET_SCHEDULER_add_now (&end_badly, "Failed to get dht handle!\n"); | ||
391 | } | ||
392 | } | ||
393 | |||
394 | /* Decrement number of peers left to start */ | ||
395 | peers_left--; | ||
396 | |||
397 | if (peers_left == 0) /* Indicates all peers started */ | ||
398 | { | ||
399 | #if VERBOSE | ||
400 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
401 | "All %d daemons started, now connecting peers!\n", num_peers); | ||
402 | #endif | ||
403 | expected_connections = -1; | ||
404 | if ((pg != NULL)) /* Sanity check */ | ||
405 | { | ||
406 | /* Connect peers in a "straight line" topology, return the number of expected connections */ | ||
407 | expected_connections = | ||
408 | GNUNET_TESTING_connect_topology (pg, GNUNET_TESTING_TOPOLOGY_LINE, | ||
409 | GNUNET_TESTING_TOPOLOGY_OPTION_ALL, | ||
410 | 0.0, TIMEOUT, 2, NULL, NULL); | ||
411 | } | ||
412 | |||
413 | /* Cancel current timeout fail task */ | ||
414 | GNUNET_SCHEDULER_cancel (die_task); | ||
415 | if (expected_connections == GNUNET_SYSERR) /* Some error happened */ | ||
416 | die_task = | ||
417 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
418 | "from connect topology (bad return)"); | ||
419 | |||
420 | /* Schedule timeout on failure task */ | ||
421 | die_task = | ||
422 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, | ||
423 | "from connect topology (timeout)"); | ||
424 | ok = 0; | ||
425 | } | ||
426 | } | ||
427 | |||
428 | static void | ||
429 | run (void *cls, char *const *args, const char *cfgfile, | ||
430 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
431 | { | ||
432 | |||
433 | /* Get path from configuration file */ | ||
434 | if (GNUNET_YES != | ||
435 | GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", | ||
436 | &test_directory)) | ||
437 | { | ||
438 | ok = 404; | ||
439 | return; | ||
440 | } | ||
441 | |||
442 | /* Get number of peers to start from configuration (should be two) */ | ||
443 | if (GNUNET_SYSERR == | ||
444 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing_old", "num_peers", | ||
445 | &num_peers)) | ||
446 | num_peers = DEFAULT_NUM_PEERS; | ||
447 | |||
448 | /* Set peers_left so we know when all peers started */ | ||
449 | peers_left = num_peers; | ||
450 | |||
451 | /* Set up a task to end testing if peer start fails */ | ||
452 | die_task = | ||
453 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, | ||
454 | "didn't start all daemons in reasonable amount of time!!!"); | ||
455 | |||
456 | /* Start num_peers peers, call peers_started_callback on peer start, topology_callback on peer connect */ | ||
457 | /* Read the API documentation for other parameters! */ | ||
458 | pg = GNUNET_TESTING_daemons_start (cfg, peers_left, /* Total number of peers */ | ||
459 | peers_left, /* Number of outstanding connections */ | ||
460 | peers_left, /* Number of parallel ssh connections, or peers being started at once */ | ||
461 | TIMEOUT, NULL, NULL, | ||
462 | &peers_started_callback, NULL, | ||
463 | &topology_callback, NULL, NULL); | ||
464 | |||
465 | } | ||
466 | |||
467 | static int | ||
468 | check () | ||
469 | { | ||
470 | int ret; | ||
471 | |||
472 | /* Arguments for GNUNET_PROGRAM_run */ | ||
473 | char *const argv[] = { "test-dht-twopeer-put-get", /* Name to give running binary */ | ||
474 | "-c", | ||
475 | "test_dht_twopeer_data.conf", /* Config file to use */ | ||
476 | #if VERBOSE | ||
477 | "-L", "DEBUG", | ||
478 | #endif | ||
479 | NULL | ||
480 | }; | ||
481 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
482 | GNUNET_GETOPT_OPTION_END | ||
483 | }; | ||
484 | /* Run the run function as a new program */ | ||
485 | ret = | ||
486 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, | ||
487 | "test-dht-twopeer-put-get", "nohelp", options, &run, | ||
488 | &ok); | ||
489 | if (ret != GNUNET_OK) | ||
490 | { | ||
491 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
492 | "`test-dht-twopeer': Failed with error code %d\n", ret); | ||
493 | } | ||
494 | return ok; | ||
495 | } | ||
496 | |||
497 | int | ||
498 | main (int argc, char *argv[]) | ||
499 | { | ||
500 | int ret; | ||
501 | |||
502 | GNUNET_log_setup ("test-dht-twopeer", | ||
503 | #if VERBOSE | ||
504 | "DEBUG", | ||
505 | #else | ||
506 | "WARNING", | ||
507 | #endif | ||
508 | NULL); | ||
509 | ret = check (); | ||
510 | /** | ||
511 | * Need to remove base directory, subdirectories taken care | ||
512 | * of by the testing framework. | ||
513 | */ | ||
514 | if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK) | ||
515 | { | ||
516 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
517 | "Failed to remove testing directory %s\n", test_directory); | ||
518 | } | ||
519 | return ret; | ||
520 | } | ||
521 | |||
522 | /* end of test_dht_twopeer_put_get.c */ | ||
diff --git a/src/dht/test_dht_twopeer_put_get.c b/src/dht/test_dht_twopeer_put_get.c deleted file mode 100644 index d577a856a..000000000 --- a/src/dht/test_dht_twopeer_put_get.c +++ /dev/null | |||
@@ -1,510 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009 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 | * @file dht/test_dht_twopeer_put_get.c | ||
22 | * @brief base testcase for testing DHT service with | ||
23 | * two running peers. | ||
24 | * | ||
25 | * This testcase starts peers using the GNUNET_TESTING_daemons_start | ||
26 | * function call. On peer start, connects to the peers DHT service | ||
27 | * by calling GNUNET_DHT_connected. Once notified about all peers | ||
28 | * being started (by the peers_started_callback function), calls | ||
29 | * GNUNET_TESTING_connect_topology, which connects the peers in a | ||
30 | * "straight line" topology. On notification that all peers have | ||
31 | * been properly connected, runs the do_put function to insert data | ||
32 | * at the first peer. Once the GNUNET_DHT_put function completes, | ||
33 | * calls the do_get function which initiates a GNUNET_DHT_get from | ||
34 | * the *second* peer. If the GET is successful, schedules finish_testing | ||
35 | * to stop the test and shut down peers. If GET is unsuccessful | ||
36 | * after GET_TIMEOUT seconds, prints an error message and shuts down | ||
37 | * the peers. | ||
38 | */ | ||
39 | #include "platform.h" | ||
40 | #include "gnunet_testing_lib.h" | ||
41 | #include "gnunet_core_service.h" | ||
42 | #include "gnunet_dht_service.h" | ||
43 | #include "block_dns.h" | ||
44 | #include "gnunet_signatures.h" | ||
45 | |||
46 | /* DEFINES */ | ||
47 | #define VERBOSE GNUNET_NO | ||
48 | |||
49 | /* Timeout for entire testcase */ | ||
50 | #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5) | ||
51 | |||
52 | /* Timeout for waiting for replies to get requests */ | ||
53 | #define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30) | ||
54 | |||
55 | /* If number of peers not in config file, use this number */ | ||
56 | #define DEFAULT_NUM_PEERS 2 | ||
57 | |||
58 | /* Globals */ | ||
59 | |||
60 | /** | ||
61 | * Directory to store temp data in, defined in config file | ||
62 | */ | ||
63 | static char *test_directory; | ||
64 | |||
65 | /** | ||
66 | * Variable used to store the number of connections we should wait for. | ||
67 | */ | ||
68 | static unsigned int expected_connections; | ||
69 | |||
70 | /** | ||
71 | * Variable used to keep track of how many peers aren't yet started. | ||
72 | */ | ||
73 | static unsigned long long peers_left; | ||
74 | |||
75 | /** | ||
76 | * Handle to the set of all peers run for this test. | ||
77 | */ | ||
78 | static struct GNUNET_TESTING_PeerGroup *pg; | ||
79 | |||
80 | /** | ||
81 | * Global handle we will use for GET requests. | ||
82 | */ | ||
83 | struct GNUNET_DHT_GetHandle *global_get_handle; | ||
84 | |||
85 | |||
86 | /** | ||
87 | * Total number of peers to run, set based on config file. | ||
88 | */ | ||
89 | static unsigned long long num_peers; | ||
90 | |||
91 | /** | ||
92 | * Global used to count how many connections we have currently | ||
93 | * been notified about (how many times has topology_callback been called | ||
94 | * with success?) | ||
95 | */ | ||
96 | static unsigned int total_connections; | ||
97 | |||
98 | /** | ||
99 | * Global used to count how many failed connections we have | ||
100 | * been notified about (how many times has topology_callback | ||
101 | * been called with failure?) | ||
102 | */ | ||
103 | static unsigned int failed_connections; | ||
104 | |||
105 | /* Task handle to use to schedule test failure */ | ||
106 | static GNUNET_SCHEDULER_TaskIdentifier die_task; | ||
107 | |||
108 | /* Global return value (0 for success, anything else for failure) */ | ||
109 | static int ok; | ||
110 | |||
111 | /** | ||
112 | * Peer identity of the first peer started. | ||
113 | */ | ||
114 | static struct GNUNET_PeerIdentity peer1id; | ||
115 | |||
116 | /** | ||
117 | * Peer identity of the second peer started. | ||
118 | */ | ||
119 | static struct GNUNET_PeerIdentity peer2id; | ||
120 | |||
121 | /** | ||
122 | * Handle to the first peers DHT service (via the API) | ||
123 | */ | ||
124 | static struct GNUNET_DHT_Handle *peer1dht; | ||
125 | |||
126 | /** | ||
127 | * Handle to the second peers DHT service (via the API) | ||
128 | */ | ||
129 | static struct GNUNET_DHT_Handle *peer2dht; | ||
130 | |||
131 | /** | ||
132 | * Handle for our PUT operation. | ||
133 | */ | ||
134 | static struct GNUNET_DHT_PutHandle *put_op; | ||
135 | |||
136 | |||
137 | /** | ||
138 | * Check whether peers successfully shut down. | ||
139 | */ | ||
140 | static void | ||
141 | shutdown_callback (void *cls, const char *emsg) | ||
142 | { | ||
143 | if (emsg != NULL) | ||
144 | { | ||
145 | if (ok == 0) | ||
146 | ok = 2; | ||
147 | } | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * Function scheduled to be run on the successful completion of this | ||
152 | * testcase. Specifically, called when our get request completes. | ||
153 | */ | ||
154 | static void | ||
155 | finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
156 | { | ||
157 | GNUNET_assert (pg != NULL); | ||
158 | GNUNET_assert (peer1dht != NULL); | ||
159 | GNUNET_assert (peer2dht != NULL); | ||
160 | GNUNET_DHT_disconnect (peer1dht); | ||
161 | GNUNET_DHT_disconnect (peer2dht); | ||
162 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
163 | ok = 0; | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut | ||
168 | * down the peers without freeing memory associated with GET request. | ||
169 | */ | ||
170 | static void | ||
171 | end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
172 | { | ||
173 | if (NULL != put_op) | ||
174 | { | ||
175 | GNUNET_DHT_put_cancel (put_op); | ||
176 | put_op = NULL; | ||
177 | } | ||
178 | if (peer1dht != NULL) | ||
179 | GNUNET_DHT_disconnect (peer1dht); | ||
180 | |||
181 | if (peer2dht != NULL) | ||
182 | GNUNET_DHT_disconnect (peer2dht); | ||
183 | |||
184 | if (pg != NULL) | ||
185 | GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL); | ||
186 | } | ||
187 | |||
188 | |||
189 | /** | ||
190 | * Check if the get_handle is being used, if so stop the request. Either | ||
191 | * way, schedule the end_badly_cont function which actually shuts down the | ||
192 | * test. | ||
193 | */ | ||
194 | static void | ||
195 | end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
196 | { | ||
197 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failing test with error: `%s'!\n", | ||
198 | (char *) cls); | ||
199 | if (global_get_handle != NULL) | ||
200 | { | ||
201 | GNUNET_DHT_get_stop (global_get_handle); | ||
202 | global_get_handle = NULL; | ||
203 | } | ||
204 | GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL); | ||
205 | ok = 1; | ||
206 | } | ||
207 | |||
208 | /** | ||
209 | * Iterator called if the GET request initiated returns a response. | ||
210 | * | ||
211 | * @param cls closure | ||
212 | * @param exp when will this value expire | ||
213 | * @param key key of the result | ||
214 | * @param type type of the result | ||
215 | * @param size number of bytes in data | ||
216 | * @param data pointer to the result data | ||
217 | */ | ||
218 | static void | ||
219 | get_result_iterator (void *cls, struct GNUNET_TIME_Absolute exp, | ||
220 | const struct GNUNET_HashCode * key, | ||
221 | const struct GNUNET_PeerIdentity *get_path, | ||
222 | unsigned int get_path_size, | ||
223 | const struct GNUNET_PeerIdentity *put_path, | ||
224 | unsigned int put_path_size, enum GNUNET_BLOCK_Type type, | ||
225 | size_t size, const void *result_data) | ||
226 | { | ||
227 | struct GNUNET_HashCode original_key; /* Key data was stored data under */ | ||
228 | char original_data[4]; /* Made up data that was stored */ | ||
229 | |||
230 | memset (&original_key, 42, sizeof (struct GNUNET_HashCode)); /* Set the key to what it was set to previously */ | ||
231 | memset (original_data, 43, sizeof (original_data)); | ||
232 | |||
233 | if ((sizeof (original_data) != size) || | ||
234 | (0 != memcmp (&original_key, key, sizeof (struct GNUNET_HashCode))) || | ||
235 | (0 != memcmp (original_data, result_data, sizeof (original_data)))) | ||
236 | { | ||
237 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
238 | "Key or data is not the same as was inserted!\n"); | ||
239 | GNUNET_SCHEDULER_cancel (die_task); | ||
240 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
241 | "key or data mismatch in get response!\n"); | ||
242 | return; | ||
243 | } | ||
244 | |||
245 | GNUNET_SCHEDULER_cancel (die_task); | ||
246 | GNUNET_DHT_get_stop (global_get_handle); | ||
247 | global_get_handle = NULL; | ||
248 | GNUNET_SCHEDULER_add_now (&finish_testing, NULL); | ||
249 | } | ||
250 | |||
251 | |||
252 | /** | ||
253 | * Called when the PUT request has been transmitted to the DHT service. | ||
254 | * Schedule the GET request for some time in the future. | ||
255 | */ | ||
256 | static void | ||
257 | put_finished (void *cls, int success) | ||
258 | { | ||
259 | struct GNUNET_HashCode key; /* Key for data lookup */ | ||
260 | |||
261 | put_op = NULL; | ||
262 | GNUNET_SCHEDULER_cancel (die_task); | ||
263 | die_task = | ||
264 | GNUNET_SCHEDULER_add_delayed (GET_TIMEOUT, &end_badly, | ||
265 | "waiting for get response (data not found)"); | ||
266 | |||
267 | memset (&key, 42, sizeof (struct GNUNET_HashCode)); /* Set the key to the same thing as when data was inserted */ | ||
268 | global_get_handle = | ||
269 | GNUNET_DHT_get_start (peer2dht, | ||
270 | GNUNET_BLOCK_TYPE_TEST, &key, 1, GNUNET_DHT_RO_NONE, | ||
271 | NULL, 0, &get_result_iterator, NULL); | ||
272 | } | ||
273 | |||
274 | |||
275 | /** | ||
276 | * Set up some data, and call API PUT function | ||
277 | */ | ||
278 | static void | ||
279 | do_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
280 | { | ||
281 | struct GNUNET_HashCode key; /* Made up key to store data under */ | ||
282 | char data[4]; /* Made up data to store */ | ||
283 | |||
284 | memset (&key, 42, sizeof (struct GNUNET_HashCode)); /* Set the key to something simple so we can issue GET request */ | ||
285 | memset (data, 43, sizeof (data)); | ||
286 | |||
287 | /* Insert the data at the first peer */ | ||
288 | put_op = GNUNET_DHT_put (peer1dht, &key, 1, GNUNET_DHT_RO_NONE, GNUNET_BLOCK_TYPE_TEST, | ||
289 | sizeof (data), data, GNUNET_TIME_UNIT_FOREVER_ABS, | ||
290 | GNUNET_TIME_UNIT_FOREVER_REL, &put_finished, NULL); | ||
291 | } | ||
292 | |||
293 | |||
294 | /** | ||
295 | * This function is called whenever a connection attempt is finished between two of | ||
296 | * the started peers (started with GNUNET_TESTING_daemons_start). The total | ||
297 | * number of times this function is called should equal the number returned | ||
298 | * from the GNUNET_TESTING_connect_topology call. | ||
299 | * | ||
300 | * The emsg variable is NULL on success (peers connected), and non-NULL on | ||
301 | * failure (peers failed to connect). | ||
302 | */ | ||
303 | static void | ||
304 | topology_callback (void *cls, const struct GNUNET_PeerIdentity *first, | ||
305 | const struct GNUNET_PeerIdentity *second, uint32_t distance, | ||
306 | const struct GNUNET_CONFIGURATION_Handle *first_cfg, | ||
307 | const struct GNUNET_CONFIGURATION_Handle *second_cfg, | ||
308 | struct GNUNET_TESTING_Daemon *first_daemon, | ||
309 | struct GNUNET_TESTING_Daemon *second_daemon, | ||
310 | const char *emsg) | ||
311 | { | ||
312 | if (emsg == NULL) | ||
313 | { | ||
314 | total_connections++; | ||
315 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
316 | "connected peer %s to peer %s, distance %u\n", | ||
317 | first_daemon->shortname, second_daemon->shortname, distance); | ||
318 | } | ||
319 | else | ||
320 | { | ||
321 | failed_connections++; | ||
322 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
323 | "Failed to connect peer %s to peer %s with error :\n%s\n", | ||
324 | first_daemon->shortname, second_daemon->shortname, emsg); | ||
325 | } | ||
326 | |||
327 | if (total_connections == expected_connections) | ||
328 | { | ||
329 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
330 | "Created %d total connections, which is our target number! Starting next phase of testing.\n", | ||
331 | total_connections); | ||
332 | GNUNET_SCHEDULER_cancel (die_task); | ||
333 | die_task = | ||
334 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, "from test gets"); | ||
335 | |||
336 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_put, NULL); | ||
337 | } | ||
338 | else if (total_connections + failed_connections == expected_connections) | ||
339 | { | ||
340 | GNUNET_SCHEDULER_cancel (die_task); | ||
341 | die_task = | ||
342 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
343 | "from topology_callback (too many failed connections)"); | ||
344 | } | ||
345 | } | ||
346 | |||
347 | |||
348 | /** | ||
349 | * Callback which is called whenever a peer is started (as a result of the | ||
350 | * GNUNET_TESTING_daemons_start call. | ||
351 | * | ||
352 | * @param cls closure argument given to GNUNET_TESTING_daemons_start | ||
353 | * @param id the GNUNET_PeerIdentity of the started peer | ||
354 | * @param cfg the configuration for this specific peer (needed to connect | ||
355 | * to the DHT) | ||
356 | * @param d the handle to the daemon started | ||
357 | * @param emsg NULL if peer started, non-NULL on error | ||
358 | */ | ||
359 | static void | ||
360 | peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id, | ||
361 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
362 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
363 | { | ||
364 | if (emsg != NULL) | ||
365 | { | ||
366 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
367 | "Failed to start daemon with error: `%s'\n", emsg); | ||
368 | return; | ||
369 | } | ||
370 | GNUNET_assert (id != NULL); | ||
371 | |||
372 | /* This is the first peer started */ | ||
373 | if (peers_left == num_peers) | ||
374 | { | ||
375 | memcpy (&peer1id, id, sizeof (struct GNUNET_PeerIdentity)); /* Save the peer id */ | ||
376 | peer1dht = GNUNET_DHT_connect (cfg, 100); /* Connect to the first peers DHT service */ | ||
377 | if (peer1dht == NULL) /* If DHT connect failed */ | ||
378 | { | ||
379 | GNUNET_SCHEDULER_cancel (die_task); | ||
380 | GNUNET_SCHEDULER_add_now (&end_badly, "Failed to get dht handle!\n"); | ||
381 | } | ||
382 | } | ||
383 | else /* This is the second peer started */ | ||
384 | { | ||
385 | memcpy (&peer2id, id, sizeof (struct GNUNET_PeerIdentity)); /* Same as for first peer... */ | ||
386 | peer2dht = GNUNET_DHT_connect (cfg, 100); | ||
387 | if (peer2dht == NULL) | ||
388 | { | ||
389 | GNUNET_SCHEDULER_cancel (die_task); | ||
390 | GNUNET_SCHEDULER_add_now (&end_badly, "Failed to get dht handle!\n"); | ||
391 | } | ||
392 | } | ||
393 | |||
394 | /* Decrement number of peers left to start */ | ||
395 | peers_left--; | ||
396 | |||
397 | if (peers_left == 0) /* Indicates all peers started */ | ||
398 | { | ||
399 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
400 | "All %d daemons started, now connecting peers!\n", num_peers); | ||
401 | expected_connections = -1; | ||
402 | if ((pg != NULL)) /* Sanity check */ | ||
403 | { | ||
404 | /* Connect peers in a "straight line" topology, return the number of expected connections */ | ||
405 | expected_connections = | ||
406 | GNUNET_TESTING_connect_topology (pg, GNUNET_TESTING_TOPOLOGY_LINE, | ||
407 | GNUNET_TESTING_TOPOLOGY_OPTION_ALL, | ||
408 | 0.0, TIMEOUT, 12, NULL, NULL); | ||
409 | } | ||
410 | |||
411 | /* Cancel current timeout fail task */ | ||
412 | GNUNET_SCHEDULER_cancel (die_task); | ||
413 | if (expected_connections == GNUNET_SYSERR) /* Some error happened */ | ||
414 | die_task = | ||
415 | GNUNET_SCHEDULER_add_now (&end_badly, | ||
416 | "from connect topology (bad return)"); | ||
417 | |||
418 | /* Schedule timeout on failure task */ | ||
419 | die_task = | ||
420 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, | ||
421 | "from connect topology (timeout)"); | ||
422 | ok = 0; | ||
423 | } | ||
424 | } | ||
425 | |||
426 | static void | ||
427 | run (void *cls, char *const *args, const char *cfgfile, | ||
428 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
429 | { | ||
430 | |||
431 | /* Get path from configuration file */ | ||
432 | if (GNUNET_YES != | ||
433 | GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", | ||
434 | &test_directory)) | ||
435 | { | ||
436 | ok = 404; | ||
437 | return; | ||
438 | } | ||
439 | |||
440 | /* Get number of peers to start from configuration (should be two) */ | ||
441 | if (GNUNET_SYSERR == | ||
442 | GNUNET_CONFIGURATION_get_value_number (cfg, "testing_old", "num_peers", | ||
443 | &num_peers)) | ||
444 | num_peers = DEFAULT_NUM_PEERS; | ||
445 | |||
446 | /* Set peers_left so we know when all peers started */ | ||
447 | peers_left = num_peers; | ||
448 | |||
449 | /* Set up a task to end testing if peer start fails */ | ||
450 | die_task = | ||
451 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, | ||
452 | "didn't start all daemons in reasonable amount of time!!!"); | ||
453 | |||
454 | /* Start num_peers peers, call peers_started_callback on peer start, topology_callback on peer connect */ | ||
455 | /* Read the API documentation for other parameters! */ | ||
456 | pg = GNUNET_TESTING_daemons_start (cfg, num_peers, 2, 2, TIMEOUT, NULL, NULL, | ||
457 | &peers_started_callback, NULL, | ||
458 | &topology_callback, NULL, NULL); | ||
459 | |||
460 | } | ||
461 | |||
462 | static int | ||
463 | check () | ||
464 | { | ||
465 | int ret; | ||
466 | |||
467 | /* Arguments for GNUNET_PROGRAM_run */ | ||
468 | char *const argv[] = { "test-dht-twopeer-put-get", /* Name to give running binary */ | ||
469 | "-c", | ||
470 | "test_dht_twopeer_data.conf", /* Config file to use */ | ||
471 | NULL | ||
472 | }; | ||
473 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
474 | GNUNET_GETOPT_OPTION_END | ||
475 | }; | ||
476 | /* Run the run function as a new program */ | ||
477 | ret = | ||
478 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, | ||
479 | "test-dht-twopeer-put-get", "nohelp", options, &run, | ||
480 | &ok); | ||
481 | if (ret != GNUNET_OK) | ||
482 | { | ||
483 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
484 | "`test-dht-twopeer': Failed with error code %d\n", ret); | ||
485 | } | ||
486 | return ok; | ||
487 | } | ||
488 | |||
489 | int | ||
490 | main (int argc, char *argv[]) | ||
491 | { | ||
492 | int ret; | ||
493 | |||
494 | GNUNET_log_setup ("test-dht-twopeer", | ||
495 | "WARNING", | ||
496 | NULL); | ||
497 | ret = check (); | ||
498 | /** | ||
499 | * Need to remove base directory, subdirectories taken care | ||
500 | * of by the testing framework. | ||
501 | */ | ||
502 | if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK) | ||
503 | { | ||
504 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
505 | "Failed to remove testing directory %s\n", test_directory); | ||
506 | } | ||
507 | return ret; | ||
508 | } | ||
509 | |||
510 | /* end of test_dht_twopeer_put_get.c */ | ||