persist_write_test.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /* Tests for persistence.
  2. *
  3. * FIXME - these need to be aggressive about finding failures, at the moment
  4. * they are just confirming that good behaviour works. */
  5. #include <CUnit/CUnit.h>
  6. #include <CUnit/Basic.h>
  7. #define WITH_BROKER
  8. #define WITH_PERSISTENCE
  9. #include "mosquitto_broker_internal.h"
  10. #include "persist.h"
  11. uint64_t last_retained;
  12. char *last_sub = NULL;
  13. int last_qos;
  14. struct mosquitto_db db;
  15. /* read entire file into memory */
  16. static int file_read(const char *filename, uint8_t **data, size_t *len)
  17. {
  18. FILE *fptr;
  19. size_t rc;
  20. fptr = fopen(filename, "rb");
  21. if(!fptr) return 1;
  22. fseek(fptr, 0, SEEK_END);
  23. *len = (size_t)ftell(fptr);
  24. *data = malloc(*len);
  25. if(!(*data)){
  26. fclose(fptr);
  27. return 1;
  28. }
  29. fseek(fptr, 0, SEEK_SET);
  30. rc = fread(*data, 1, *len, fptr);
  31. fclose(fptr);
  32. if(rc == *len){
  33. return 0;
  34. }else{
  35. *len = 0;
  36. free(*data);
  37. return 1;
  38. }
  39. }
  40. /* Crude file diff, only for small files */
  41. static int file_diff(const char *one, const char *two)
  42. {
  43. size_t len1, len2;
  44. uint8_t *data1 = NULL, *data2 = NULL;
  45. int rc = 1;
  46. if(file_read(one, &data1, &len1)){
  47. return 1;
  48. }
  49. if(file_read(two, &data2, &len2)){
  50. free(data1);
  51. return 1;
  52. }
  53. if(len1 == len2){
  54. rc = memcmp(data1, data2, len1);
  55. }
  56. free(data1);
  57. free(data2);
  58. return rc;
  59. }
  60. static void TEST_persistence_disabled(void)
  61. {
  62. struct mosquitto__config config;
  63. int rc;
  64. memset(&db, 0, sizeof(struct mosquitto_db));
  65. memset(&config, 0, sizeof(struct mosquitto__config));
  66. db.config = &config;
  67. config.persistence = true;
  68. rc = persist__backup(false);
  69. CU_ASSERT_EQUAL(rc, MOSQ_ERR_INVAL);
  70. config.persistence_filepath = "disabled.db";
  71. rc = persist__backup(false);
  72. CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
  73. }
  74. static void TEST_empty_file(void)
  75. {
  76. struct mosquitto__config config;
  77. int rc;
  78. memset(&db, 0, sizeof(struct mosquitto_db));
  79. memset(&config, 0, sizeof(struct mosquitto__config));
  80. db.config = &config;
  81. config.persistence = true;
  82. config.persistence_filepath = "empty.db";
  83. rc = persist__backup(false);
  84. CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
  85. CU_ASSERT_EQUAL(0, file_diff("files/persist_write/empty.test-db", "empty.db"));
  86. unlink("empty.db");
  87. }
  88. static void TEST_v6_config_ok(void)
  89. {
  90. struct mosquitto__config config;
  91. int rc;
  92. memset(&db, 0, sizeof(struct mosquitto_db));
  93. memset(&config, 0, sizeof(struct mosquitto__config));
  94. db.config = &config;
  95. config.persistence = true;
  96. config.persistence_filepath = "files/persist_read/v6-cfg.test-db";
  97. rc = persist__restore();
  98. CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
  99. config.persistence_filepath = "v6-cfg.db";
  100. rc = persist__backup(true);
  101. CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
  102. CU_ASSERT_EQUAL(0, file_diff("files/persist_read/v6-cfg.test-db", "v6-cfg.db"));
  103. unlink("v6-cfg.db");
  104. }
  105. static void TEST_v6_message_store_no_ref(void)
  106. {
  107. struct mosquitto__config config;
  108. int rc;
  109. memset(&db, 0, sizeof(struct mosquitto_db));
  110. memset(&config, 0, sizeof(struct mosquitto__config));
  111. db.config = &config;
  112. config.persistence = true;
  113. config.persistence_filepath = "files/persist_read/v6-message-store.test-db";
  114. rc = persist__restore();
  115. CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
  116. config.persistence_filepath = "v6-message-store-no-ref.db";
  117. rc = persist__backup(true);
  118. CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
  119. CU_ASSERT_EQUAL(0, file_diff("files/persist_write/v6-message-store-no-ref.test-db", "v6-message-store-no-ref.db"));
  120. unlink("v6-message-store-no-ref.db");
  121. }
  122. static void TEST_v6_message_store_props(void)
  123. {
  124. struct mosquitto__config config;
  125. struct mosquitto__listener listener;
  126. int rc;
  127. memset(&db, 0, sizeof(struct mosquitto_db));
  128. memset(&config, 0, sizeof(struct mosquitto__config));
  129. memset(&listener, 0, sizeof(struct mosquitto__listener));
  130. db.config = &config;
  131. listener.port = 1883;
  132. config.per_listener_settings = true;
  133. config.listeners = &listener;
  134. config.listener_count = 1;
  135. config.persistence = true;
  136. config.persistence_filepath = "files/persist_read/v6-message-store-props.test-db";
  137. rc = persist__restore();
  138. CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
  139. config.persistence_filepath = "v6-message-store-props.db";
  140. rc = persist__backup(true);
  141. CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
  142. CU_ASSERT_EQUAL(0, file_diff("files/persist_read/v6-message-store-props.test-db", "v6-message-store-props.db"));
  143. unlink("v6-message-store-props.db");
  144. }
  145. static void TEST_v6_client(void)
  146. {
  147. struct mosquitto__config config;
  148. struct mosquitto__listener listener;
  149. int rc;
  150. memset(&db, 0, sizeof(struct mosquitto_db));
  151. memset(&config, 0, sizeof(struct mosquitto__config));
  152. memset(&listener, 0, sizeof(struct mosquitto__listener));
  153. db.config = &config;
  154. listener.port = 1883;
  155. config.per_listener_settings = true;
  156. config.listeners = &listener;
  157. config.listener_count = 1;
  158. config.persistence = true;
  159. config.persistence_filepath = "files/persist_read/v6-client.test-db";
  160. rc = persist__restore();
  161. CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
  162. config.persistence_filepath = "v6-client.db";
  163. rc = persist__backup(true);
  164. CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
  165. CU_ASSERT_EQUAL(0, file_diff("files/persist_read/v6-client.test-db", "v6-client.db"));
  166. unlink("v6-client.db");
  167. }
  168. static void TEST_v6_client_message(void)
  169. {
  170. struct mosquitto__config config;
  171. struct mosquitto__listener listener;
  172. int rc;
  173. memset(&db, 0, sizeof(struct mosquitto_db));
  174. memset(&config, 0, sizeof(struct mosquitto__config));
  175. memset(&listener, 0, sizeof(struct mosquitto__listener));
  176. db.config = &config;
  177. listener.port = 1883;
  178. config.per_listener_settings = true;
  179. config.listeners = &listener;
  180. config.listener_count = 1;
  181. config.persistence = true;
  182. config.persistence_filepath = "files/persist_read/v6-client-message.test-db";
  183. rc = persist__restore();
  184. CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
  185. config.persistence_filepath = "v6-client-message.db";
  186. rc = persist__backup(true);
  187. CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
  188. CU_ASSERT_EQUAL(0, file_diff("files/persist_read/v6-client-message.test-db", "v6-client-message.db"));
  189. unlink("v6-client-message.db");
  190. }
  191. static void TEST_v6_client_message_props(void)
  192. {
  193. struct mosquitto__config config;
  194. struct mosquitto__listener listener;
  195. int rc;
  196. memset(&db, 0, sizeof(struct mosquitto_db));
  197. memset(&config, 0, sizeof(struct mosquitto__config));
  198. memset(&listener, 0, sizeof(struct mosquitto__listener));
  199. db.config = &config;
  200. listener.port = 1883;
  201. config.per_listener_settings = true;
  202. config.listeners = &listener;
  203. config.listener_count = 1;
  204. config.persistence = true;
  205. config.persistence_filepath = "files/persist_read/v6-client-message-props.test-db";
  206. rc = persist__restore();
  207. CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
  208. CU_ASSERT_PTR_NOT_NULL(db.msg_store);
  209. if(db.msg_store){
  210. CU_ASSERT_PTR_NOT_NULL(db.msg_store->source_listener);
  211. if(db.msg_store->source_listener){
  212. CU_ASSERT_EQUAL(db.msg_store->source_listener->port, 1883);
  213. }
  214. }
  215. config.persistence_filepath = "v6-client-message-props.db";
  216. rc = persist__backup(true);
  217. CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
  218. CU_ASSERT_EQUAL(0, file_diff("files/persist_read/v6-client-message-props.test-db", "v6-client-message-props.db"));
  219. unlink("v6-client-message-props.db");
  220. }
  221. static void TEST_v6_sub(void)
  222. {
  223. struct mosquitto__config config;
  224. struct mosquitto__listener listener;
  225. int rc;
  226. memset(&db, 0, sizeof(struct mosquitto_db));
  227. memset(&config, 0, sizeof(struct mosquitto__config));
  228. memset(&listener, 0, sizeof(struct mosquitto__listener));
  229. db.config = &config;
  230. listener.port = 1883;
  231. config.per_listener_settings = true;
  232. config.listeners = &listener;
  233. config.listener_count = 1;
  234. db__open(&config);
  235. config.persistence = true;
  236. config.persistence_filepath = "files/persist_read/v6-sub.test-db";
  237. rc = persist__restore();
  238. CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
  239. config.persistence_filepath = "v6-sub.db";
  240. rc = persist__backup(true);
  241. CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
  242. CU_ASSERT_EQUAL(0, file_diff("files/persist_read/v6-sub.test-db", "v6-sub.db"));
  243. unlink("v6-sub.db");
  244. }
  245. #if 0
  246. NOT WORKING
  247. static void TEST_v5_full(void)
  248. {
  249. struct mosquitto__config config;
  250. int rc;
  251. memset(&db, 0, sizeof(struct mosquitto_db));
  252. memset(&config, 0, sizeof(struct mosquitto__config));
  253. db.config = &config;
  254. db__open(&config);
  255. config.persistence = true;
  256. config.persistence_filepath = "files/persist_write/v5-full.test-db";
  257. rc = persist__restore();
  258. CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
  259. config.persistence_filepath = "v5-full.db";
  260. rc = persist__backup(true);
  261. CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS);
  262. CU_ASSERT_EQUAL(0, file_diff("files/persist_write/v5-full.test-db", "v5-full.db"));
  263. unlink("v5-full.db");
  264. }
  265. #endif
  266. /* ========================================================================
  267. * TEST SUITE SETUP
  268. * ======================================================================== */
  269. int main(int argc, char *argv[])
  270. {
  271. CU_pSuite test_suite = NULL;
  272. unsigned int fails;
  273. UNUSED(argc);
  274. UNUSED(argv);
  275. if(CU_initialize_registry() != CUE_SUCCESS){
  276. printf("Error initializing CUnit registry.\n");
  277. return 1;
  278. }
  279. test_suite = CU_add_suite("Persist write", NULL, NULL);
  280. if(!test_suite){
  281. printf("Error adding CUnit persist write test suite.\n");
  282. CU_cleanup_registry();
  283. return 1;
  284. }
  285. if(0
  286. || !CU_add_test(test_suite, "Persistence disabled", TEST_persistence_disabled)
  287. || !CU_add_test(test_suite, "Empty file", TEST_empty_file)
  288. || !CU_add_test(test_suite, "v6 config ok", TEST_v6_config_ok)
  289. || !CU_add_test(test_suite, "v6 message store (message has no refs)", TEST_v6_message_store_no_ref)
  290. || !CU_add_test(test_suite, "v6 message store + props", TEST_v6_message_store_props)
  291. || !CU_add_test(test_suite, "v6 client", TEST_v6_client)
  292. || !CU_add_test(test_suite, "v6 client message", TEST_v6_client_message)
  293. || !CU_add_test(test_suite, "v6 client message+props", TEST_v6_client_message_props)
  294. || !CU_add_test(test_suite, "v6 sub", TEST_v6_sub)
  295. //|| !CU_add_test(test_suite, "v5 full", TEST_v5_full)
  296. ){
  297. printf("Error adding persist CUnit tests.\n");
  298. CU_cleanup_registry();
  299. return 1;
  300. }
  301. CU_basic_set_mode(CU_BRM_VERBOSE);
  302. CU_basic_run_tests();
  303. fails = CU_get_number_of_failures();
  304. CU_cleanup_registry();
  305. return (int)fails;
  306. }