test_mdns.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /*
  2. * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Unlicense OR CC0-1.0
  5. */
  6. #include <string.h>
  7. #include "mdns.h"
  8. #include "esp_event.h"
  9. #include "unity.h"
  10. #include "test_utils.h"
  11. #include "unity_fixture.h"
  12. #include "memory_checks.h"
  13. #define MDNS_HOSTNAME "test-hostname"
  14. #define MDNS_DELEGATE_HOSTNAME "delegate-hostname"
  15. #define MDNS_INSTANCE "test-instance"
  16. #define MDNS_SERVICE_NAME "_http"
  17. #define MDNS_SERVICE_PROTO "_tcp"
  18. #define MDNS_SERVICE_PORT 80
  19. TEST_GROUP(mdns);
  20. TEST_SETUP(mdns)
  21. {
  22. test_utils_record_free_mem();
  23. TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL));
  24. }
  25. TEST_TEAR_DOWN(mdns)
  26. {
  27. test_utils_finish_and_evaluate_leaks(32, 64);
  28. }
  29. static void yield_to_all_priorities(void)
  30. {
  31. // Lower the test-task priority before testing to ensure other tasks got executed on forced context switch
  32. size_t test_task_prio_before = uxTaskPriorityGet(NULL);
  33. vTaskPrioritySet(NULL, tskIDLE_PRIORITY);
  34. taskYIELD(); // Let the RTOS to switch context
  35. vTaskPrioritySet(NULL, test_task_prio_before);
  36. }
  37. TEST(mdns, api_fails_with_invalid_state)
  38. {
  39. TEST_ASSERT_NOT_EQUAL(ESP_OK, mdns_init() );
  40. TEST_ASSERT_NOT_EQUAL(ESP_OK, mdns_hostname_set(MDNS_HOSTNAME) );
  41. TEST_ASSERT_NOT_EQUAL(ESP_OK, mdns_instance_name_set(MDNS_INSTANCE) );
  42. TEST_ASSERT_NOT_EQUAL(ESP_OK, mdns_service_add(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT, NULL, 0) );
  43. }
  44. TEST(mdns, init_deinit)
  45. {
  46. test_case_uses_tcpip();
  47. TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default());
  48. TEST_ASSERT_EQUAL(ESP_OK, mdns_init() );
  49. yield_to_all_priorities(); // Make sure that mdns task has executed to complete initialization
  50. mdns_free();
  51. esp_event_loop_delete_default();
  52. }
  53. TEST(mdns, api_fails_with_expected_err)
  54. {
  55. mdns_txt_item_t serviceTxtData[CONFIG_MDNS_MAX_SERVICES] = { {NULL, NULL},
  56. };
  57. mdns_ip_addr_t addr;
  58. addr.addr.type = ESP_IPADDR_TYPE_V4;
  59. addr.addr.u_addr.ip4.addr = esp_ip4addr_aton("127.0.0.1");
  60. addr.next = NULL;
  61. for (int i = 0; i < CONFIG_MDNS_MAX_SERVICES; ++i) {
  62. serviceTxtData[i].key = "Key";
  63. serviceTxtData[i].value = "Value";
  64. }
  65. test_case_uses_tcpip();
  66. TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default());
  67. TEST_ASSERT_EQUAL(ESP_OK, mdns_init() );
  68. TEST_ASSERT_EQUAL(ESP_OK, mdns_hostname_set(MDNS_HOSTNAME) );
  69. TEST_ASSERT_EQUAL(ESP_OK, mdns_delegate_hostname_add(MDNS_DELEGATE_HOSTNAME, &addr) );
  70. yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
  71. TEST_ASSERT_TRUE(mdns_hostname_exists(MDNS_DELEGATE_HOSTNAME) );
  72. TEST_ASSERT_EQUAL(ESP_OK, mdns_instance_name_set(MDNS_INSTANCE) );
  73. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_add(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT, serviceTxtData, CONFIG_MDNS_MAX_SERVICES) );
  74. TEST_ASSERT_FALSE(mdns_service_exists(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME) );
  75. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_add_for_host(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME,
  76. MDNS_SERVICE_PORT, serviceTxtData, CONFIG_MDNS_MAX_SERVICES) );
  77. TEST_ASSERT_TRUE(mdns_service_exists(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME) );
  78. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_txt_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, serviceTxtData, CONFIG_MDNS_MAX_SERVICES) );
  79. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_txt_item_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, "key1", "value1") );
  80. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_txt_item_remove(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, "key1") );
  81. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_port_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 8080) );
  82. yield_to_all_priorities(); // to remove the service with the updated txt records
  83. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_remove(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO) );
  84. yield_to_all_priorities(); // Make sure that mdns task has executed to remove the service
  85. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_add(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT, NULL, 0) );
  86. TEST_ASSERT_EQUAL(ESP_OK, mdns_delegate_hostname_remove(MDNS_DELEGATE_HOSTNAME) );
  87. yield_to_all_priorities(); // Make sure that mdns task has executed to remove the hostname
  88. TEST_ASSERT_FALSE(mdns_service_exists(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME) );
  89. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_remove_all() );
  90. yield_to_all_priorities(); // Make sure that mdns task has executed to remove all services
  91. TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, mdns_service_port_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 8080) );
  92. mdns_free();
  93. esp_event_loop_delete_default();
  94. }
  95. TEST(mdns, query_api_fails_with_expected_err)
  96. {
  97. mdns_result_t *results = NULL;
  98. esp_ip6_addr_t addr6;
  99. esp_ip4_addr_t addr4;
  100. test_case_uses_tcpip();
  101. TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default());
  102. TEST_ASSERT_EQUAL(ESP_OK, mdns_init() );
  103. // check it is not possible to register a service or set an instance without configuring the hostname
  104. TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, mdns_service_add(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT, NULL, 0));
  105. TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, mdns_instance_name_set(MDNS_INSTANCE));
  106. TEST_ASSERT_EQUAL(ESP_OK, mdns_hostname_set(MDNS_HOSTNAME));
  107. // hostname is set, now adding a service and instance should succeed
  108. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_add(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT, NULL, 0));
  109. TEST_ASSERT_EQUAL(ESP_OK, mdns_instance_name_set(MDNS_INSTANCE));
  110. TEST_ASSERT_EQUAL(ESP_OK, mdns_query_ptr(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 10, CONFIG_MDNS_MAX_SERVICES, &results) );
  111. mdns_query_results_free(results);
  112. TEST_ASSERT_EQUAL(ESP_OK, mdns_query_srv(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 10, &results) );
  113. mdns_query_results_free(results);
  114. TEST_ASSERT_EQUAL(ESP_OK, mdns_query_txt(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 10, &results) );
  115. mdns_query_results_free(results);
  116. TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, mdns_query_a(MDNS_HOSTNAME, 10, &addr4) );
  117. mdns_query_results_free(results);
  118. TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, mdns_query_aaaa(MDNS_HOSTNAME, 10, &addr6) );
  119. mdns_query_results_free(results);
  120. mdns_free();
  121. esp_event_loop_delete_default();
  122. }
  123. TEST(mdns, add_remove_service)
  124. {
  125. mdns_result_t *results = NULL;
  126. test_case_uses_tcpip();
  127. TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default());
  128. TEST_ASSERT_EQUAL(ESP_OK, mdns_init() );
  129. TEST_ASSERT_EQUAL(ESP_OK, mdns_hostname_set(MDNS_HOSTNAME));
  130. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_add(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT, NULL, 0));
  131. yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
  132. TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_selfhosted_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
  133. TEST_ASSERT_NOT_EQUAL(NULL, results);
  134. TEST_ASSERT_EQUAL_STRING(MDNS_INSTANCE, results->instance_name);
  135. TEST_ASSERT_EQUAL_STRING(MDNS_SERVICE_NAME, results->service_type);
  136. TEST_ASSERT_EQUAL(MDNS_SERVICE_PORT, results->port);
  137. TEST_ASSERT_EQUAL(NULL, results->txt);
  138. mdns_query_results_free(results);
  139. // Update service properties: port
  140. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_port_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT + 1));
  141. yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
  142. TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_selfhosted_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
  143. TEST_ASSERT_NOT_EQUAL(NULL, results);
  144. TEST_ASSERT_EQUAL(MDNS_SERVICE_PORT + 1, results->port);
  145. mdns_query_results_free(results);
  146. // Update service properties: instance
  147. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_instance_name_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_INSTANCE "1" ));
  148. yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
  149. TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_selfhosted_service(MDNS_INSTANCE "1", MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
  150. TEST_ASSERT_NOT_EQUAL(NULL, results);
  151. TEST_ASSERT_EQUAL_STRING(MDNS_INSTANCE "1", results->instance_name);
  152. mdns_query_results_free(results);
  153. // Update service properties: txt
  154. mdns_txt_item_t txt_data[] = {
  155. {"key1", "esp32"},
  156. {"key2", "value"},
  157. {"key3", "value3"},
  158. };
  159. const size_t txt_data_cout = sizeof(txt_data) / sizeof(txt_data[0]);
  160. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_txt_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, txt_data, txt_data_cout));
  161. yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
  162. TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_selfhosted_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
  163. TEST_ASSERT_NOT_EQUAL(NULL, results);
  164. TEST_ASSERT_NOT_EQUAL(NULL, results->txt);
  165. TEST_ASSERT_EQUAL(txt_data_cout, results->txt_count);
  166. // compare txt values by keys
  167. size_t matches = 0;
  168. for (int i = 0; i < results->txt_count; ++i) // iterates over the results we get from mdns_lookup()
  169. for (int j = 0; j < txt_data_cout; ++j) // iterates over our test records
  170. if (strcmp(results->txt[i].key, txt_data[j].key) == 0) { // we compare the value only if the key matches
  171. TEST_ASSERT_EQUAL_STRING(results->txt[i].value, txt_data[j].value);
  172. ++matches;
  173. }
  174. TEST_ASSERT_EQUAL(txt_data_cout, matches); // checks that we went over all our txt items
  175. mdns_query_results_free(results);
  176. // Now remove the service
  177. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_remove(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO));
  178. yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
  179. TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_selfhosted_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
  180. TEST_ASSERT_EQUAL(NULL, results);
  181. mdns_free();
  182. esp_event_loop_delete_default();
  183. }
  184. TEST(mdns, add_remove_deleg_service)
  185. {
  186. mdns_ip_addr_t addr;
  187. addr.addr.type = ESP_IPADDR_TYPE_V4;
  188. addr.addr.u_addr.ip4.addr = esp_ip4addr_aton("127.0.0.1");
  189. addr.next = NULL;
  190. mdns_result_t *results = NULL;
  191. test_case_uses_tcpip();
  192. TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default());
  193. TEST_ASSERT_EQUAL(ESP_OK, mdns_init() );
  194. TEST_ASSERT_EQUAL(ESP_OK, mdns_hostname_set(MDNS_HOSTNAME));
  195. TEST_ASSERT_EQUAL(ESP_OK, mdns_delegate_hostname_add(MDNS_DELEGATE_HOSTNAME, &addr) );
  196. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_add_for_host(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME, MDNS_SERVICE_PORT, NULL, 0));
  197. yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
  198. TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_delegated_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
  199. TEST_ASSERT_NOT_EQUAL(NULL, results);
  200. TEST_ASSERT_EQUAL_STRING(MDNS_INSTANCE, results->instance_name);
  201. TEST_ASSERT_EQUAL_STRING(MDNS_SERVICE_NAME, results->service_type);
  202. TEST_ASSERT_EQUAL(MDNS_SERVICE_PORT, results->port);
  203. TEST_ASSERT_EQUAL(NULL, results->txt);
  204. mdns_query_results_free(results);
  205. // Update service properties: port
  206. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_port_set_for_host(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME, MDNS_SERVICE_PORT + 1));
  207. yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
  208. TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_delegated_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
  209. TEST_ASSERT_NOT_EQUAL(NULL, results);
  210. TEST_ASSERT_EQUAL(MDNS_SERVICE_PORT + 1, results->port);
  211. mdns_query_results_free(results);
  212. // Update service properties: instance
  213. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_instance_name_set_for_host(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME, MDNS_INSTANCE "1" ));
  214. yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
  215. TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_delegated_service(MDNS_INSTANCE "1", MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
  216. TEST_ASSERT_NOT_EQUAL(NULL, results);
  217. TEST_ASSERT_EQUAL_STRING(MDNS_INSTANCE "1", results->instance_name);
  218. mdns_query_results_free(results);
  219. // Update service properties: txt
  220. mdns_txt_item_t txt_data[] = {
  221. {"key1", "esp32"},
  222. {"key2", "value"},
  223. };
  224. const size_t txt_data_cout = sizeof(txt_data) / sizeof(txt_data[0]);
  225. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_txt_set_for_host(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME, txt_data, txt_data_cout));
  226. yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
  227. TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_delegated_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
  228. TEST_ASSERT_NOT_EQUAL(NULL, results);
  229. TEST_ASSERT_NOT_EQUAL(NULL, results->txt);
  230. TEST_ASSERT_EQUAL(txt_data_cout, results->txt_count);
  231. // compare txt values by keys
  232. size_t matches = 0;
  233. for (int i = 0; i < results->txt_count; ++i) // iterates over the results we get from mdns_lookup()
  234. for (int j = 0; j < txt_data_cout; ++j) // iterates over our test records
  235. if (strcmp(results->txt[i].key, txt_data[j].key) == 0) { // we compare the value only if the key matches
  236. TEST_ASSERT_EQUAL_STRING(results->txt[i].value, txt_data[j].value);
  237. ++matches;
  238. }
  239. TEST_ASSERT_EQUAL(txt_data_cout, matches); // checks that we went over all our txt items
  240. mdns_query_results_free(results);
  241. // Now remove the service
  242. TEST_ASSERT_EQUAL(ESP_OK, mdns_service_remove_for_host(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME));
  243. yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname
  244. TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_delegated_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results));
  245. TEST_ASSERT_EQUAL(NULL, results);
  246. mdns_free();
  247. esp_event_loop_delete_default();
  248. }
  249. TEST_GROUP_RUNNER(mdns)
  250. {
  251. RUN_TEST_CASE(mdns, api_fails_with_invalid_state)
  252. RUN_TEST_CASE(mdns, api_fails_with_expected_err)
  253. RUN_TEST_CASE(mdns, query_api_fails_with_expected_err)
  254. RUN_TEST_CASE(mdns, init_deinit)
  255. RUN_TEST_CASE(mdns, add_remove_service)
  256. RUN_TEST_CASE(mdns, add_remove_deleg_service)
  257. }
  258. void app_main(void)
  259. {
  260. UNITY_MAIN(mdns);
  261. }