test_datastore_api_management.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2004, 2005, 2006, 2007, 2009, 2011 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /*
  17. * @file datastore/test_datastore_api_management.c
  18. * @brief Test for the space management functions of the datastore implementation.
  19. * @author Christian Grothoff
  20. */
  21. #include "platform.h"
  22. #include "gnunet_util_lib.h"
  23. #include "gnunet_protocols.h"
  24. #include "gnunet_datastore_service.h"
  25. #include "gnunet_datastore_plugin.h"
  26. #include "gnunet_testing_lib.h"
  27. /**
  28. * How long until we give up on transmitting the message?
  29. */
  30. #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
  31. /**
  32. * Number of iterations to run; must be large enough
  33. * so that the quota will be exceeded!
  34. */
  35. #define ITERATIONS 5000
  36. enum RunPhase
  37. {
  38. RP_PUT,
  39. RP_GET,
  40. RP_DONE,
  41. RP_GET_FAIL
  42. };
  43. struct CpsRunContext
  44. {
  45. struct GNUNET_HashCode key;
  46. int i;
  47. int found;
  48. const struct GNUNET_CONFIGURATION_Handle *cfg;
  49. void *data;
  50. enum RunPhase phase;
  51. };
  52. static struct GNUNET_DATASTORE_Handle *datastore;
  53. static struct GNUNET_TIME_Absolute now;
  54. static int ok;
  55. static const char *plugin_name;
  56. static size_t
  57. get_size (int i)
  58. {
  59. return 8 + 8 * (i % 256);
  60. }
  61. static const void *
  62. get_data (int i)
  63. {
  64. static char buf[60000];
  65. memset (buf, i, 8 + 8 * (i % 256));
  66. return buf;
  67. }
  68. static int
  69. get_type (int i)
  70. {
  71. return 1;
  72. }
  73. static int
  74. get_priority (int i)
  75. {
  76. return i + 1;
  77. }
  78. static int
  79. get_anonymity (int i)
  80. {
  81. return i;
  82. }
  83. static struct GNUNET_TIME_Absolute
  84. get_expiration (int i)
  85. {
  86. struct GNUNET_TIME_Absolute av;
  87. av.abs_value_us = now.abs_value_us + i * 1000 * 1000LL;
  88. return av;
  89. }
  90. static void
  91. run_continuation (void *cls);
  92. static void
  93. check_success (void *cls, int success, struct GNUNET_TIME_Absolute min_expiration, const char *msg)
  94. {
  95. struct CpsRunContext *crc = cls;
  96. if (GNUNET_OK != success)
  97. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", msg);
  98. GNUNET_assert (GNUNET_OK == success);
  99. GNUNET_free_non_null (crc->data);
  100. crc->data = NULL;
  101. GNUNET_SCHEDULER_add_now (&run_continuation, crc);
  102. }
  103. static void
  104. check_value (void *cls,
  105. const struct GNUNET_HashCode *key,
  106. size_t size,
  107. const void *data,
  108. enum GNUNET_BLOCK_Type type,
  109. uint32_t priority,
  110. uint32_t anonymity,
  111. uint32_t replication,
  112. struct GNUNET_TIME_Absolute expiration,
  113. uint64_t uid)
  114. {
  115. struct CpsRunContext *crc = cls;
  116. int i;
  117. if (NULL == key)
  118. {
  119. crc->phase = RP_GET_FAIL;
  120. GNUNET_SCHEDULER_add_now (&run_continuation, crc);
  121. return;
  122. }
  123. i = crc->i;
  124. GNUNET_assert (size == get_size (i));
  125. GNUNET_assert (0 == memcmp (data, get_data (i), size));
  126. GNUNET_assert (type == get_type (i));
  127. GNUNET_assert (priority == get_priority (i));
  128. GNUNET_assert (anonymity == get_anonymity (i));
  129. GNUNET_assert (expiration.abs_value_us == get_expiration (i).abs_value_us);
  130. crc->i--;
  131. if (crc->i == 0)
  132. crc->phase = RP_DONE;
  133. GNUNET_SCHEDULER_add_now (&run_continuation, crc);
  134. }
  135. static void
  136. check_nothing (void *cls,
  137. const struct GNUNET_HashCode *key,
  138. size_t size,
  139. const void *data,
  140. enum GNUNET_BLOCK_Type type,
  141. uint32_t priority,
  142. uint32_t anonymity,
  143. uint32_t replication,
  144. struct GNUNET_TIME_Absolute expiration,
  145. uint64_t uid)
  146. {
  147. struct CpsRunContext *crc = cls;
  148. GNUNET_assert (key == NULL);
  149. if (0 == --crc->i)
  150. crc->phase = RP_DONE;
  151. GNUNET_SCHEDULER_add_now (&run_continuation, crc);
  152. }
  153. static void
  154. run_continuation (void *cls)
  155. {
  156. struct CpsRunContext *crc = cls;
  157. ok = (int) crc->phase;
  158. switch (crc->phase)
  159. {
  160. case RP_PUT:
  161. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing `%s' number %u\n", "PUT",
  162. crc->i);
  163. GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key);
  164. GNUNET_DATASTORE_put (datastore,
  165. 0,
  166. &crc->key,
  167. get_size (crc->i),
  168. get_data (crc->i),
  169. get_type (crc->i),
  170. get_priority (crc->i),
  171. get_anonymity (crc->i),
  172. 0,
  173. get_expiration (crc->i),
  174. 1,
  175. 1,
  176. &check_success, crc);
  177. crc->i++;
  178. if (crc->i == ITERATIONS)
  179. {
  180. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  181. "Sleeping to give datastore time to clean up\n");
  182. sleep (1);
  183. crc->phase = RP_GET;
  184. crc->i--;
  185. }
  186. break;
  187. case RP_GET:
  188. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing `%s' number %u\n", "GET",
  189. crc->i);
  190. GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key);
  191. GNUNET_DATASTORE_get_key (datastore,
  192. 0,
  193. false,
  194. &crc->key,
  195. get_type (crc->i),
  196. 1,
  197. 1,
  198. &check_value,
  199. crc);
  200. break;
  201. case RP_GET_FAIL:
  202. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing `%s' number %u\n", "GET(f)",
  203. crc->i);
  204. GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key);
  205. GNUNET_DATASTORE_get_key (datastore,
  206. 0,
  207. false,
  208. &crc->key,
  209. get_type (crc->i),
  210. 1,
  211. 1,
  212. &check_nothing,
  213. crc);
  214. break;
  215. case RP_DONE:
  216. GNUNET_assert (0 == crc->i);
  217. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished, disconnecting\n");
  218. GNUNET_DATASTORE_disconnect (datastore, GNUNET_YES);
  219. GNUNET_free (crc);
  220. ok = 0;
  221. }
  222. }
  223. static void
  224. run_tests (void *cls, int success, struct GNUNET_TIME_Absolute min_expiration, const char *msg)
  225. {
  226. struct CpsRunContext *crc = cls;
  227. if (success != GNUNET_YES)
  228. {
  229. FPRINTF (stderr,
  230. "Test 'put' operation failed with error `%s' database likely not setup, skipping test.\n",
  231. msg);
  232. GNUNET_DATASTORE_disconnect (datastore, GNUNET_YES);
  233. GNUNET_free (crc);
  234. return;
  235. }
  236. GNUNET_SCHEDULER_add_now (&run_continuation, crc);
  237. }
  238. static void
  239. run (void *cls,
  240. const struct GNUNET_CONFIGURATION_Handle *cfg,
  241. struct GNUNET_TESTING_Peer *peer)
  242. {
  243. struct CpsRunContext *crc;
  244. static struct GNUNET_HashCode zkey;
  245. crc = GNUNET_new (struct CpsRunContext);
  246. crc->cfg = cfg;
  247. crc->phase = RP_PUT;
  248. now = GNUNET_TIME_absolute_get ();
  249. datastore = GNUNET_DATASTORE_connect (cfg);
  250. if (NULL ==
  251. GNUNET_DATASTORE_put (datastore,
  252. 0,
  253. &zkey,
  254. 4,
  255. "TEST",
  256. GNUNET_BLOCK_TYPE_TEST,
  257. 0, 0, 0,
  258. GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_SECONDS),
  259. 0,
  260. 1,
  261. &run_tests,
  262. crc))
  263. {
  264. FPRINTF (stderr, "%s", "Test 'put' operation failed.\n");
  265. GNUNET_free (crc);
  266. ok = 1;
  267. }
  268. }
  269. /**
  270. * Function called when disk utilization changes, does nothing.
  271. *
  272. * @param cls closure
  273. * @param delta change in utilization
  274. */
  275. static void
  276. ignore_payload_cb (void *cls,
  277. int delta)
  278. {
  279. /* do nothing */
  280. }
  281. /**
  282. * check if plugin is actually working
  283. */
  284. static int
  285. test_plugin (const char *cfg_name)
  286. {
  287. char libname[PATH_MAX];
  288. struct GNUNET_CONFIGURATION_Handle *cfg;
  289. struct GNUNET_DATASTORE_PluginFunctions *api;
  290. struct GNUNET_DATASTORE_PluginEnvironment env;
  291. cfg = GNUNET_CONFIGURATION_create ();
  292. if (GNUNET_OK !=
  293. GNUNET_CONFIGURATION_load (cfg,
  294. cfg_name))
  295. {
  296. GNUNET_CONFIGURATION_destroy (cfg);
  297. fprintf (stderr,
  298. "Failed to load configuration %s\n",
  299. cfg_name);
  300. return 1;
  301. }
  302. memset (&env, 0, sizeof (env));
  303. env.cfg = cfg;
  304. env.duc = &ignore_payload_cb;
  305. GNUNET_snprintf (libname,
  306. sizeof (libname),
  307. "libgnunet_plugin_datastore_%s",
  308. plugin_name);
  309. api = GNUNET_PLUGIN_load (libname, &env);
  310. if (NULL == api)
  311. {
  312. GNUNET_CONFIGURATION_destroy (cfg);
  313. fprintf (stderr,
  314. "Failed to load plugin `%s'\n",
  315. libname);
  316. return 77;
  317. }
  318. GNUNET_PLUGIN_unload (libname, api);
  319. GNUNET_CONFIGURATION_destroy (cfg);
  320. return 0;
  321. }
  322. int
  323. main (int argc, char *argv[])
  324. {
  325. char cfg_name[PATH_MAX];
  326. int ret;
  327. plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]);
  328. GNUNET_snprintf (cfg_name,
  329. sizeof (cfg_name),
  330. "test_datastore_api_data_%s.conf",
  331. plugin_name);
  332. ret = test_plugin (cfg_name);
  333. if (0 != ret)
  334. return ret;
  335. if (0 !=
  336. GNUNET_TESTING_peer_run ("test-gnunet-datastore-management",
  337. cfg_name,
  338. &run,
  339. NULL))
  340. return 1;
  341. return ok;
  342. }
  343. /* end of test_datastore_api_management.c */