mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-29 18:27:31 +02:00
feat(mdns): Add linux console functional tests
This commit is contained in:
23
.github/workflows/mdns__host-tests.yml
vendored
23
.github/workflows/mdns__host-tests.yml
vendored
@ -10,27 +10,30 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
host_test_mdns:
|
host_test_mdns:
|
||||||
if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push'
|
if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push'
|
||||||
name: Host test
|
name: Host test build
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
container: espressif/idf:release-v5.1
|
container: espressif/idf:release-v5.3
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout esp-protocols
|
- name: Checkout esp-protocols
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
path: esp-protocols
|
path: protocols
|
||||||
|
|
||||||
- name: Build and Test
|
- name: Build and Test
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
apt-get update && apt-get install -y dnsutils gcc g++
|
|
||||||
. ${IDF_PATH}/export.sh
|
. ${IDF_PATH}/export.sh
|
||||||
cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/tests/host_test
|
python -m pip install idf-build-apps dnspython pytest pytest-embedded pytest-embedded-serial-esp pytest-embedded-idf
|
||||||
idf.py build
|
cd $GITHUB_WORKSPACE/protocols
|
||||||
./build/mdns_host.elf &
|
# Build host tests app (with all configs and targets supported)
|
||||||
dig +short -p 5353 @224.0.0.251 myesp.local > ip.txt
|
python ./ci/build_apps.py components/mdns/tests/host_test/
|
||||||
cat ip.txt | xargs dig +short -p 5353 @224.0.0.251 -x
|
cd components/mdns/tests/host_test
|
||||||
cat ip.txt
|
# First run the linux_app and send a quick A query and a reverse query
|
||||||
|
./build_linux_app/mdns_host.elf &
|
||||||
|
python dnsfixture.py A myesp.local --ip_only | xargs python dnsfixture.py X
|
||||||
|
# Next we run the pytest (using the console app)
|
||||||
|
pytest
|
||||||
|
|
||||||
build_afl_host_test_mdns:
|
build_afl_host_test_mdns:
|
||||||
if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push'
|
if: contains(github.event.pull_request.labels.*.name, 'mdns') || github.event_name == 'push'
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
idf_component_register()
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -12,8 +12,24 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "osal/osal_api.h"
|
#include "osal/osal_api.h"
|
||||||
|
#include <semaphore.h>
|
||||||
|
|
||||||
|
typedef struct task_notifiers {
|
||||||
|
sem_t sem;
|
||||||
|
TaskHandle_t id;
|
||||||
|
} task_notifiers_t;
|
||||||
|
|
||||||
|
typedef struct pthread_params {
|
||||||
|
void *const param;
|
||||||
|
TaskFunction_t task;
|
||||||
|
bool started;
|
||||||
|
TaskHandle_t handle;
|
||||||
|
} pthread_params_t;
|
||||||
|
|
||||||
static uint64_t s_semaphore_data = 0;
|
static uint64_t s_semaphore_data = 0;
|
||||||
|
static task_notifiers_t *s_notifiers;
|
||||||
|
static int s_threads = 0;
|
||||||
|
pthread_mutex_t s_mutex;
|
||||||
|
|
||||||
typedef enum queue_type_tag {
|
typedef enum queue_type_tag {
|
||||||
MUTEX_REC,
|
MUTEX_REC,
|
||||||
@ -89,6 +105,7 @@ BaseType_t xSemaphoreGiveRecursive( QueueHandle_t xQueue)
|
|||||||
}
|
}
|
||||||
return pdFALSE;
|
return pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask )
|
BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask )
|
||||||
{
|
{
|
||||||
struct generic_queue_handle *h = xQueue;
|
struct generic_queue_handle *h = xQueue;
|
||||||
@ -99,7 +116,6 @@ BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask )
|
|||||||
return xQueueReceive(xQueue, &s_semaphore_data, portMAX_DELAY);
|
return xQueueReceive(xQueue, &s_semaphore_data, portMAX_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BaseType_t xSemaphoreTakeRecursive( QueueHandle_t xQueue, TickType_t pvTask )
|
BaseType_t xSemaphoreTakeRecursive( QueueHandle_t xQueue, TickType_t pvTask )
|
||||||
{
|
{
|
||||||
struct generic_queue_handle *h = xQueue;
|
struct generic_queue_handle *h = xQueue;
|
||||||
@ -110,9 +126,6 @@ BaseType_t xSemaphoreTakeRecursive( QueueHandle_t xQueue, TickType_t pvTask )
|
|||||||
return pdFALSE;
|
return pdFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void vQueueDelete( QueueHandle_t xQueue )
|
void vQueueDelete( QueueHandle_t xQueue )
|
||||||
{
|
{
|
||||||
struct generic_queue_handle *h = xQueue;
|
struct generic_queue_handle *h = xQueue;
|
||||||
@ -128,8 +141,7 @@ void vQueueDelete( QueueHandle_t xQueue )
|
|||||||
|
|
||||||
QueueHandle_t xSemaphoreCreateBinary(void)
|
QueueHandle_t xSemaphoreCreateBinary(void)
|
||||||
{
|
{
|
||||||
QueueHandle_t sempaphore = xQueueCreate(1, 1);
|
return xQueueCreate(1, 1);
|
||||||
return sempaphore;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueHandle_t xSemaphoreCreateMutex(void)
|
QueueHandle_t xSemaphoreCreateMutex(void)
|
||||||
@ -145,6 +157,13 @@ QueueHandle_t xSemaphoreCreateRecursiveMutex(void)
|
|||||||
|
|
||||||
void vTaskDelete(TaskHandle_t *task)
|
void vTaskDelete(TaskHandle_t *task)
|
||||||
{
|
{
|
||||||
|
for (int i = 0; i < s_threads; ++i) {
|
||||||
|
if (task == s_notifiers[i].id) {
|
||||||
|
sem_destroy(&s_notifiers[i].sem);
|
||||||
|
s_notifiers[i].id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (task == NULL) {
|
if (task == NULL) {
|
||||||
pthread_exit(0);
|
pthread_exit(0);
|
||||||
}
|
}
|
||||||
@ -171,14 +190,21 @@ void vTaskDelay( const TickType_t xTicksToDelay )
|
|||||||
|
|
||||||
void *pthread_task(void *params)
|
void *pthread_task(void *params)
|
||||||
{
|
{
|
||||||
struct {
|
pthread_params_t *pthread_params = params;
|
||||||
void *const param;
|
|
||||||
TaskFunction_t task;
|
|
||||||
bool started;
|
|
||||||
} *pthread_params = params;
|
|
||||||
|
|
||||||
void *const param = pthread_params->param;
|
void *const param = pthread_params->param;
|
||||||
TaskFunction_t task = pthread_params->task;
|
TaskFunction_t task = pthread_params->task;
|
||||||
|
|
||||||
|
pthread_params->handle = xTaskGetCurrentTaskHandle();
|
||||||
|
if (s_threads == 0) {
|
||||||
|
pthread_mutex_init(&s_mutex, NULL);
|
||||||
|
}
|
||||||
|
pthread_mutex_lock(&s_mutex);
|
||||||
|
s_notifiers = realloc(s_notifiers, sizeof(struct task_notifiers) * (++s_threads));
|
||||||
|
assert(s_notifiers);
|
||||||
|
s_notifiers[s_threads - 1].id = pthread_params->handle;
|
||||||
|
sem_init(&s_notifiers[s_threads - 1].sem, 0, 0);
|
||||||
|
pthread_mutex_unlock(&s_mutex);
|
||||||
pthread_params->started = true;
|
pthread_params->started = true;
|
||||||
|
|
||||||
task(param);
|
task(param);
|
||||||
@ -198,16 +224,12 @@ BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode,
|
|||||||
return pdTRUE;
|
return pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, const uint32_t usStackDepth, void *const pvParameters, UBaseType_t uxPriority, TaskHandle_t *const pvCreatedTask)
|
BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, const uint32_t usStackDepth, void *const pvParameters, UBaseType_t uxPriority, TaskHandle_t *const pvCreatedTask)
|
||||||
{
|
{
|
||||||
pthread_t new_thread = (pthread_t)NULL;
|
pthread_t new_thread = (pthread_t)NULL;
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
struct {
|
pthread_params_t pthread_params = { .param = pvParameters, .task = pvTaskCode};
|
||||||
void *const param;
|
|
||||||
TaskFunction_t task;
|
|
||||||
bool started;
|
|
||||||
} pthread_params = { .param = pvParameters, .task = pvTaskCode};
|
|
||||||
int res = pthread_attr_init(&attr);
|
int res = pthread_attr_init(&attr);
|
||||||
assert(res == 0);
|
assert(res == 0);
|
||||||
res = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
res = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
||||||
@ -215,20 +237,33 @@ BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, cons
|
|||||||
res = pthread_create(&new_thread, &attr, pthread_task, &pthread_params);
|
res = pthread_create(&new_thread, &attr, pthread_task, &pthread_params);
|
||||||
assert(res == 0);
|
assert(res == 0);
|
||||||
|
|
||||||
if (pvCreatedTask) {
|
|
||||||
*pvCreatedTask = (void *)new_thread;
|
|
||||||
}
|
|
||||||
|
|
||||||
// just wait till the task started so we can unwind params from the stack
|
// just wait till the task started so we can unwind params from the stack
|
||||||
while (pthread_params.started == false) {
|
while (pthread_params.started == false) {
|
||||||
usleep(1000);
|
usleep(1000);
|
||||||
}
|
}
|
||||||
|
if (pvCreatedTask) {
|
||||||
|
*pvCreatedTask = pthread_params.handle;
|
||||||
|
}
|
||||||
|
|
||||||
return pdTRUE;
|
return pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xTaskNotifyGive(TaskHandle_t task)
|
void xTaskNotifyGive(TaskHandle_t task)
|
||||||
{
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (true) {
|
||||||
|
pthread_mutex_lock(&s_mutex);
|
||||||
|
if (task == s_notifiers[i].id) {
|
||||||
|
sem_post(&s_notifiers[i].sem);
|
||||||
|
pthread_mutex_unlock(&s_mutex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&s_mutex);
|
||||||
|
if (++i == s_threads) {
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
usleep(1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time )
|
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time )
|
||||||
@ -238,7 +273,7 @@ BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear,
|
|||||||
|
|
||||||
TaskHandle_t xTaskGetCurrentTaskHandle(void)
|
TaskHandle_t xTaskGetCurrentTaskHandle(void)
|
||||||
{
|
{
|
||||||
return NULL;
|
return (TaskHandle_t)pthread_self();
|
||||||
}
|
}
|
||||||
|
|
||||||
EventGroupHandle_t xEventGroupCreate( void )
|
EventGroupHandle_t xEventGroupCreate( void )
|
||||||
@ -270,3 +305,22 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits
|
|||||||
{
|
{
|
||||||
return osal_signal_wait(xEventGroup, uxBitsToWaitFor, xWaitForAllBits, xTicksToWait);
|
return osal_signal_wait(xEventGroup, uxBitsToWaitFor, xWaitForAllBits, xTicksToWait);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ulTaskNotifyTake(bool clear_on_exit, uint32_t xTicksToWait)
|
||||||
|
{
|
||||||
|
TaskHandle_t task = xTaskGetCurrentTaskHandle();
|
||||||
|
int i = 0;
|
||||||
|
while (true) {
|
||||||
|
pthread_mutex_lock(&s_mutex);
|
||||||
|
if (task == s_notifiers[i].id) {
|
||||||
|
pthread_mutex_unlock(&s_mutex);
|
||||||
|
sem_wait(&s_notifiers[i].sem);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&s_mutex);
|
||||||
|
if (++i == s_threads) {
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
usleep(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
#pragma once
|
@ -11,6 +11,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define tskNO_AFFINITY ( ( BaseType_t ) 0x7FFFFFFF )
|
||||||
#define TaskHandle_t TaskHandle_t
|
#define TaskHandle_t TaskHandle_t
|
||||||
#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) )
|
#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) )
|
||||||
|
|
||||||
@ -18,6 +19,8 @@ void vTaskDelay( const TickType_t xTicksToDelay );
|
|||||||
|
|
||||||
void xTaskNotifyGive(TaskHandle_t task);
|
void xTaskNotifyGive(TaskHandle_t task);
|
||||||
|
|
||||||
|
void ulTaskNotifyTake(bool stuff, uint32_t timeout);
|
||||||
|
|
||||||
TaskHandle_t xTaskGetCurrentTaskHandle(void);
|
TaskHandle_t xTaskGetCurrentTaskHandle(void);
|
||||||
|
|
||||||
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time );
|
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time );
|
||||||
|
@ -12,8 +12,9 @@ endif()
|
|||||||
|
|
||||||
idf_build_get_property(target IDF_TARGET)
|
idf_build_get_property(target IDF_TARGET)
|
||||||
if(${target} STREQUAL "linux")
|
if(${target} STREQUAL "linux")
|
||||||
set(dependencies esp_netif_linux esp_timer esp_system)
|
set(dependencies esp_netif_linux esp_event)
|
||||||
set(srcs "mdns.c" ${MDNS_NETWORKING})
|
set(private_dependencies esp_timer console esp_system)
|
||||||
|
set(srcs "mdns.c" ${MDNS_NETWORKING} ${MDNS_CONSOLE})
|
||||||
else()
|
else()
|
||||||
set(dependencies lwip console esp_netif)
|
set(dependencies lwip console esp_netif)
|
||||||
set(private_dependencies esp_timer esp_wifi)
|
set(private_dependencies esp_timer esp_wifi)
|
||||||
|
@ -29,9 +29,6 @@ static void _mdns_browse_send(mdns_browse_t *browse);
|
|||||||
#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH
|
#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH
|
||||||
#include "esp_eth.h"
|
#include "esp_eth.h"
|
||||||
#endif
|
#endif
|
||||||
#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP
|
|
||||||
#include "esp_wifi.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ESP_IDF_VERSION <= ESP_IDF_VERSION_VAL(5, 1, 0)
|
#if ESP_IDF_VERSION <= ESP_IDF_VERSION_VAL(5, 1, 0)
|
||||||
#define MDNS_ESP_WIFI_ENABLED CONFIG_SOC_WIFI_SUPPORTED
|
#define MDNS_ESP_WIFI_ENABLED CONFIG_SOC_WIFI_SUPPORTED
|
||||||
@ -39,6 +36,10 @@ static void _mdns_browse_send(mdns_browse_t *browse);
|
|||||||
#define MDNS_ESP_WIFI_ENABLED CONFIG_ESP_WIFI_ENABLED
|
#define MDNS_ESP_WIFI_ENABLED CONFIG_ESP_WIFI_ENABLED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MDNS_ESP_WIFI_ENABLED && (CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP)
|
||||||
|
#include "esp_wifi.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MDNS_ENABLE_DEBUG
|
#ifdef MDNS_ENABLE_DEBUG
|
||||||
void mdns_debug_packet(const uint8_t *data, size_t len);
|
void mdns_debug_packet(const uint8_t *data, size_t len);
|
||||||
#endif
|
#endif
|
||||||
@ -4411,7 +4412,7 @@ void mdns_preset_if_handle_system_event(void *arg, esp_event_base_t event_base,
|
|||||||
}
|
}
|
||||||
|
|
||||||
esp_netif_dhcp_status_t dcst;
|
esp_netif_dhcp_status_t dcst;
|
||||||
#if MDNS_ESP_WIFI_ENABLED
|
#if MDNS_ESP_WIFI_ENABLED && (CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP)
|
||||||
if (event_base == WIFI_EVENT) {
|
if (event_base == WIFI_EVENT) {
|
||||||
switch (event_id) {
|
switch (event_id) {
|
||||||
case WIFI_EVENT_STA_CONNECTED:
|
case WIFI_EVENT_STA_CONNECTED:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -9,6 +9,7 @@
|
|||||||
#include "argtable3/argtable3.h"
|
#include "argtable3/argtable3.h"
|
||||||
#include "mdns.h"
|
#include "mdns.h"
|
||||||
#include "mdns_private.h"
|
#include "mdns_private.h"
|
||||||
|
#include "inttypes.h"
|
||||||
|
|
||||||
static const char *ip_protocol_str[] = {"V4", "V6", "MAX"};
|
static const char *ip_protocol_str[] = {"V4", "V6", "MAX"};
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ static void mdns_print_results(mdns_result_t *results)
|
|||||||
printf(" SRV : %s.local:%u\n", r->hostname, r->port);
|
printf(" SRV : %s.local:%u\n", r->hostname, r->port);
|
||||||
}
|
}
|
||||||
if (r->txt_count) {
|
if (r->txt_count) {
|
||||||
printf(" TXT : [%u] ", r->txt_count);
|
printf(" TXT : [%u] ", (int)r->txt_count);
|
||||||
for (size_t t = 0; t < r->txt_count; t++) {
|
for (size_t t = 0; t < r->txt_count; t++) {
|
||||||
printf("%s=%s; ", r->txt[t].key, r->txt[t].value);
|
printf("%s=%s; ", r->txt[t].key, r->txt[t].value);
|
||||||
}
|
}
|
||||||
@ -516,7 +517,7 @@ static int cmd_mdns_init(int argc, char **argv)
|
|||||||
printf("MDNS: Hostname: %s\n", mdns_init_args.hostname->sval[0]);
|
printf("MDNS: Hostname: %s\n", mdns_init_args.hostname->sval[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mdns_init_args.instance->sval[0]) {
|
if (mdns_init_args.instance->count) {
|
||||||
ESP_ERROR_CHECK( mdns_instance_name_set(mdns_init_args.instance->sval[0]) );
|
ESP_ERROR_CHECK( mdns_instance_name_set(mdns_init_args.instance->sval[0]) );
|
||||||
printf("MDNS: Instance: %s\n", mdns_init_args.instance->sval[0]);
|
printf("MDNS: Instance: %s\n", mdns_init_args.instance->sval[0]);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
set(EXTRA_COMPONENT_DIRS "../.." "../../../../common_components/linux_compat")
|
|
||||||
|
|
||||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
set(COMPONENTS main esp_netif_linux)
|
if(${IDF_TARGET} STREQUAL "linux")
|
||||||
|
set(EXTRA_COMPONENT_DIRS "../../../../common_components/linux_compat")
|
||||||
|
set(COMPONENTS main)
|
||||||
|
endif()
|
||||||
|
|
||||||
project(mdns_host)
|
project(mdns_host)
|
||||||
|
|
||||||
# Enable sanitizers for mdns implementation
|
# Enable sanitizers only without console (we'd see some leaks on argtable when console exits)
|
||||||
|
if(NOT CONFIG_TEST_CONSOLE AND CONFIG_IDF_TARGET_LINUX)
|
||||||
idf_component_get_property(mdns mdns COMPONENT_LIB)
|
idf_component_get_property(mdns mdns COMPONENT_LIB)
|
||||||
target_link_options(${mdns} INTERFACE -fsanitize=address -fsanitize=undefined)
|
target_link_options(${mdns} INTERFACE -fsanitize=address -fsanitize=undefined)
|
||||||
|
endif()
|
||||||
|
@ -1,2 +1,8 @@
|
|||||||
idf_component_register(SRCS esp_netif_linux.c
|
idf_build_get_property(idf_target IDF_TARGET)
|
||||||
INCLUDE_DIRS include $ENV{IDF_PATH}/components/esp_netif/include)
|
if(${IDF_TARGET} STREQUAL "linux")
|
||||||
|
idf_component_register(SRCS esp_netif_linux.c
|
||||||
|
INCLUDE_DIRS include $ENV{IDF_PATH}/components/esp_netif/include
|
||||||
|
REQUIRES esp_event)
|
||||||
|
else()
|
||||||
|
idf_component_register()
|
||||||
|
endif()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -15,9 +15,12 @@
|
|||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include "esp_netif_types.h"
|
#include "esp_netif_types.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
#define MAX_NETIFS 4
|
#define MAX_NETIFS 4
|
||||||
|
|
||||||
|
static const char *TAG = "esp_netif_linux";
|
||||||
|
|
||||||
static esp_netif_t *s_netif_list[MAX_NETIFS] = { 0 };
|
static esp_netif_t *s_netif_list[MAX_NETIFS] = { 0 };
|
||||||
|
|
||||||
struct esp_netif_obj {
|
struct esp_netif_obj {
|
||||||
@ -50,6 +53,7 @@ esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_
|
|||||||
struct sockaddr_in *pAddr = (struct sockaddr_in *) tmp->ifa_addr;
|
struct sockaddr_in *pAddr = (struct sockaddr_in *) tmp->ifa_addr;
|
||||||
inet_ntop(AF_INET, &pAddr->sin_addr, addr, sizeof(addr) );
|
inet_ntop(AF_INET, &pAddr->sin_addr, addr, sizeof(addr) );
|
||||||
if (strcmp(esp_netif->if_desc, tmp->ifa_name) == 0) {
|
if (strcmp(esp_netif->if_desc, tmp->ifa_name) == 0) {
|
||||||
|
ESP_LOGD(TAG, "AF_INET4: %s: %s\n", tmp->ifa_name, addr);
|
||||||
memcpy(&ip_info->ip.addr, &pAddr->sin_addr, 4);
|
memcpy(&ip_info->ip.addr, &pAddr->sin_addr, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,7 +107,7 @@ esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if
|
|||||||
struct sockaddr_in6 *pAddr = (struct sockaddr_in6 *)tmp->ifa_addr;
|
struct sockaddr_in6 *pAddr = (struct sockaddr_in6 *)tmp->ifa_addr;
|
||||||
inet_ntop(AF_INET6, &pAddr->sin6_addr, addr, sizeof(addr) );
|
inet_ntop(AF_INET6, &pAddr->sin6_addr, addr, sizeof(addr) );
|
||||||
if (strcmp(esp_netif->if_desc, tmp->ifa_name) == 0) {
|
if (strcmp(esp_netif->if_desc, tmp->ifa_name) == 0) {
|
||||||
printf("AF_INET6: %s: %s\n", tmp->ifa_name, addr);
|
ESP_LOGD(TAG, "AF_INET6: %s: %s\n", tmp->ifa_name, addr);
|
||||||
memcpy(if_ip6->addr, &pAddr->sin6_addr, 4 * 4);
|
memcpy(if_ip6->addr, &pAddr->sin6_addr, 4 * 4);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -173,3 +177,8 @@ void esp_netif_destroy(esp_netif_t *esp_netif)
|
|||||||
}
|
}
|
||||||
free(esp_netif);
|
free(esp_netif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *esp_netif_get_ifkey(esp_netif_t *esp_netif)
|
||||||
|
{
|
||||||
|
return esp_netif->if_key;
|
||||||
|
}
|
||||||
|
128
components/mdns/tests/host_test/dnsfixture.py
Normal file
128
components/mdns/tests/host_test/dnsfixture.py
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
import logging
|
||||||
|
import re
|
||||||
|
import socket
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import dns.message
|
||||||
|
import dns.query
|
||||||
|
import dns.rdataclass
|
||||||
|
import dns.rdatatype
|
||||||
|
import dns.resolver
|
||||||
|
|
||||||
|
# Configure logging
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class DnsPythonWrapper:
|
||||||
|
def __init__(self, server='224.0.0.251', port=5353, retries=3):
|
||||||
|
self.server = server
|
||||||
|
self.port = port
|
||||||
|
self.retries = retries
|
||||||
|
|
||||||
|
def send_and_receive_query(self, query, timeout=3):
|
||||||
|
logger.info(f'Sending DNS query to {self.server}:{self.port}')
|
||||||
|
try:
|
||||||
|
# Create a UDP socket
|
||||||
|
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
|
||||||
|
sock.settimeout(timeout)
|
||||||
|
|
||||||
|
# Send the DNS query
|
||||||
|
query_data = query.to_wire()
|
||||||
|
sock.sendto(query_data, (self.server, self.port))
|
||||||
|
|
||||||
|
# Receive the DNS response
|
||||||
|
response_data, _ = sock.recvfrom(512) # 512 bytes is the typical size for a DNS response
|
||||||
|
|
||||||
|
# Parse the response
|
||||||
|
response = dns.message.from_wire(response_data)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
except socket.timeout as e:
|
||||||
|
logger.warning(f'DNS query timed out: {e}')
|
||||||
|
return None
|
||||||
|
except dns.exception.DNSException as e:
|
||||||
|
logger.error(f'DNS query failed: {e}')
|
||||||
|
return None
|
||||||
|
|
||||||
|
def run_query(self, name, query_type='PTR', timeout=3):
|
||||||
|
logger.info(f'Running DNS query for {name} with type {query_type}')
|
||||||
|
query = dns.message.make_query(name, dns.rdatatype.from_text(query_type), dns.rdataclass.IN)
|
||||||
|
|
||||||
|
# Print the DNS question section
|
||||||
|
logger.info(f'DNS question section: {query.question}')
|
||||||
|
|
||||||
|
# Send and receive the DNS query
|
||||||
|
response = None
|
||||||
|
for attempt in range(1, self.retries + 1):
|
||||||
|
logger.info(f'Attempt {attempt}/{self.retries}')
|
||||||
|
response = self.send_and_receive_query(query, timeout)
|
||||||
|
if response:
|
||||||
|
break
|
||||||
|
|
||||||
|
if response:
|
||||||
|
logger.info(f'DNS query response:\n{response}')
|
||||||
|
else:
|
||||||
|
logger.warning('No response received or response was invalid.')
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
def parse_answer_section(self, response, query_type):
|
||||||
|
answers = []
|
||||||
|
if response:
|
||||||
|
for answer in response.answer:
|
||||||
|
if dns.rdatatype.to_text(answer.rdtype) == query_type:
|
||||||
|
for item in answer.items:
|
||||||
|
full_answer = (
|
||||||
|
f'{answer.name} {answer.ttl} '
|
||||||
|
f'{dns.rdataclass.to_text(answer.rdclass)} '
|
||||||
|
f'{dns.rdatatype.to_text(answer.rdtype)} '
|
||||||
|
f'{item.to_text()}'
|
||||||
|
)
|
||||||
|
answers.append(full_answer)
|
||||||
|
return answers
|
||||||
|
|
||||||
|
def check_record(self, name, query_type, expected=True):
|
||||||
|
output = self.run_query(name, query_type=query_type)
|
||||||
|
answers = self.parse_answer_section(output, query_type)
|
||||||
|
logger.info(f'answers: {answers}')
|
||||||
|
if expected:
|
||||||
|
assert any(name in answer for answer in answers), f"Expected service '{name}' not found in answer section"
|
||||||
|
else:
|
||||||
|
assert not any(name in answer for answer in answers), f"Unexpected service '{name}' found in answer section"
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if len(sys.argv) < 3:
|
||||||
|
print('Usage: python dns_fixture.py <query_type> <name>')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
query_type = sys.argv[1]
|
||||||
|
name = sys.argv[2]
|
||||||
|
ip_only = len(sys.argv) > 3 and sys.argv[3] == '--ip_only'
|
||||||
|
if ip_only:
|
||||||
|
logger.setLevel(logging.WARNING)
|
||||||
|
|
||||||
|
dns_wrapper = DnsPythonWrapper()
|
||||||
|
if query_type == 'X' and '.' in name:
|
||||||
|
# Sends an IPv4 reverse query
|
||||||
|
reversed_ip = '.'.join(reversed(name.split('.')))
|
||||||
|
name = f'{reversed_ip}.in-addr.arpa'
|
||||||
|
query_type = 'PTR'
|
||||||
|
response = dns_wrapper.run_query(name, query_type=query_type)
|
||||||
|
answers = dns_wrapper.parse_answer_section(response, query_type)
|
||||||
|
|
||||||
|
if answers:
|
||||||
|
for answer in answers:
|
||||||
|
logger.info(f'DNS query response: {answer}')
|
||||||
|
if ip_only:
|
||||||
|
ipv4_pattern = re.compile(r'\b(?:\d{1,3}\.){3}\d{1,3}\b')
|
||||||
|
ipv4_addresses = ipv4_pattern.findall(answer)
|
||||||
|
if ipv4_addresses:
|
||||||
|
print(f"{', '.join(ipv4_addresses)}")
|
||||||
|
else:
|
||||||
|
logger.info(f'No response for {name} with query type {query_type}')
|
||||||
|
exit(9) # Same as dig timeout
|
@ -1,4 +1,4 @@
|
|||||||
idf_component_register(SRCS "main.c"
|
idf_component_register(SRCS "main.c"
|
||||||
INCLUDE_DIRS
|
INCLUDE_DIRS
|
||||||
"."
|
"."
|
||||||
REQUIRES mdns)
|
REQUIRES mdns console nvs_flash)
|
||||||
|
@ -12,4 +12,10 @@ menu "Test Configuration"
|
|||||||
help
|
help
|
||||||
Name/ID if the network interface on which we run the mDNS host test
|
Name/ID if the network interface on which we run the mDNS host test
|
||||||
|
|
||||||
|
config TEST_CONSOLE
|
||||||
|
bool "Start console"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Test uses esp_console for interactive testing.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
7
components/mdns/tests/host_test/main/idf_component.yml
Normal file
7
components/mdns/tests/host_test/main/idf_component.yml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
dependencies:
|
||||||
|
idf: ">=5.0"
|
||||||
|
espressif/mdns:
|
||||||
|
version: "^1.0.0"
|
||||||
|
override_path: "../../.."
|
||||||
|
protocol_examples_common:
|
||||||
|
path: ${IDF_PATH}/examples/common_components/protocol_examples_common
|
@ -1,16 +1,30 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
*/
|
*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "mdns.h"
|
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
#include "esp_console.h"
|
||||||
|
#include "mdns.h"
|
||||||
|
#include "mdns_console.h"
|
||||||
|
|
||||||
static const char *TAG = "mdns-test";
|
static const char *TAG = "mdns-test";
|
||||||
|
|
||||||
|
static void mdns_test_app(esp_netif_t *interface);
|
||||||
|
|
||||||
|
#ifdef CONFIG_TEST_CONSOLE
|
||||||
|
static EventGroupHandle_t s_exit_signal = NULL;
|
||||||
|
|
||||||
|
static int exit_console(int argc, char **argv)
|
||||||
|
{
|
||||||
|
xEventGroupSetBits(s_exit_signal, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
static void query_mdns_host(const char *host_name)
|
static void query_mdns_host(const char *host_name)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Query A: %s.local", host_name);
|
ESP_LOGI(TAG, "Query A: %s.local", host_name);
|
||||||
@ -30,37 +44,83 @@ static void query_mdns_host(const char *host_name)
|
|||||||
|
|
||||||
ESP_LOGI(TAG, "Query A: %s.local resolved to: " IPSTR, host_name, IP2STR(&addr));
|
ESP_LOGI(TAG, "Query A: %s.local resolved to: " IPSTR, host_name, IP2STR(&addr));
|
||||||
}
|
}
|
||||||
|
#endif // TEST_CONSOLE
|
||||||
|
|
||||||
|
#ifndef CONFIG_IDF_TARGET_LINUX
|
||||||
|
#include "protocol_examples_common.h"
|
||||||
|
#include "esp_event.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This is an entry point for the real target device,
|
||||||
|
* need to init few components and connect to a network interface
|
||||||
|
*/
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
ESP_ERROR_CHECK(nvs_flash_init());
|
||||||
|
ESP_ERROR_CHECK(esp_netif_init());
|
||||||
|
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||||
|
ESP_ERROR_CHECK(example_connect());
|
||||||
|
|
||||||
|
mdns_test_app(EXAMPLE_INTERFACE);
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(example_disconnect());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This is an entry point for the linux target (simulator on host)
|
||||||
|
* need to create a dummy WiFi station and use it as mdns network interface
|
||||||
|
*/
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
|
||||||
setvbuf(stdout, NULL, _IONBF, 0);
|
setvbuf(stdout, NULL, _IONBF, 0);
|
||||||
const esp_netif_inherent_config_t base_cg = { .if_key = "WIFI_STA_DEF", .if_desc = CONFIG_TEST_NETIF_NAME };
|
const esp_netif_inherent_config_t base_cg = { .if_key = "WIFI_STA_DEF", .if_desc = CONFIG_TEST_NETIF_NAME };
|
||||||
esp_netif_config_t cfg = { .base = &base_cg };
|
esp_netif_config_t cfg = { .base = &base_cg };
|
||||||
esp_netif_t *sta = esp_netif_new(&cfg);
|
esp_netif_t *sta = esp_netif_new(&cfg);
|
||||||
|
|
||||||
|
mdns_test_app(sta);
|
||||||
|
|
||||||
|
esp_netif_destroy(sta);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void mdns_test_app(esp_netif_t *interface)
|
||||||
|
{
|
||||||
ESP_ERROR_CHECK(mdns_init());
|
ESP_ERROR_CHECK(mdns_init());
|
||||||
ESP_ERROR_CHECK(mdns_hostname_set(CONFIG_TEST_HOSTNAME));
|
ESP_ERROR_CHECK(mdns_hostname_set(CONFIG_TEST_HOSTNAME));
|
||||||
ESP_LOGI(TAG, "mdns hostname set to: [%s]", CONFIG_TEST_HOSTNAME);
|
ESP_LOGI(TAG, "mdns hostname set to: [%s]", CONFIG_TEST_HOSTNAME);
|
||||||
ESP_ERROR_CHECK(mdns_register_netif(sta));
|
ESP_ERROR_CHECK(mdns_register_netif(interface));
|
||||||
ESP_ERROR_CHECK(mdns_netif_action(sta, MDNS_EVENT_ENABLE_IP4 | MDNS_EVENT_IP4_REVERSE_LOOKUP | MDNS_EVENT_IP6_REVERSE_LOOKUP));
|
ESP_ERROR_CHECK(mdns_netif_action(interface, MDNS_EVENT_ENABLE_IP4 /*| MDNS_EVENT_ENABLE_IP6 */ | MDNS_EVENT_IP4_REVERSE_LOOKUP | MDNS_EVENT_IP6_REVERSE_LOOKUP));
|
||||||
|
|
||||||
#ifdef REGISTER_SERVICE
|
#ifdef CONFIG_TEST_CONSOLE
|
||||||
//set default mDNS instance name
|
esp_console_repl_t *repl = NULL;
|
||||||
mdns_instance_name_set("myesp-inst");
|
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
|
||||||
//structure with TXT records
|
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
|
||||||
mdns_txt_item_t serviceTxtData[3] = {
|
s_exit_signal = xEventGroupCreate();
|
||||||
{"board", "esp32"},
|
|
||||||
{"u", "user"},
|
repl_config.prompt = "mdns>";
|
||||||
{"p", "password"}
|
// init console REPL environment
|
||||||
|
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
|
||||||
|
|
||||||
|
const esp_console_cmd_t cmd_exit = {
|
||||||
|
.command = "exit",
|
||||||
|
.help = "exit mDNS console application",
|
||||||
|
.hint = NULL,
|
||||||
|
.func = exit_console,
|
||||||
|
.argtable = NULL
|
||||||
};
|
};
|
||||||
vTaskDelay(pdMS_TO_TICKS(10000));
|
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd_exit) );
|
||||||
ESP_ERROR_CHECK(mdns_service_add("myesp-service2", "_http", "_tcp", 80, serviceTxtData, 3));
|
mdns_console_register();
|
||||||
#endif
|
ESP_ERROR_CHECK(esp_console_start_repl(repl));
|
||||||
|
xEventGroupWaitBits(s_exit_signal, 1, pdTRUE, pdFALSE, portMAX_DELAY);
|
||||||
|
repl->del(repl);
|
||||||
|
#else
|
||||||
vTaskDelay(pdMS_TO_TICKS(10000));
|
vTaskDelay(pdMS_TO_TICKS(10000));
|
||||||
query_mdns_host("david-work");
|
query_mdns_host("david-work");
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
esp_netif_destroy(sta);
|
#endif
|
||||||
mdns_free();
|
mdns_free();
|
||||||
ESP_LOGI(TAG, "Exit");
|
ESP_LOGI(TAG, "Exit");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
72
components/mdns/tests/host_test/pytest_mdns.py
Normal file
72
components/mdns/tests/host_test/pytest_mdns.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import pexpect
|
||||||
|
import pytest
|
||||||
|
from dnsfixture import DnsPythonWrapper
|
||||||
|
|
||||||
|
# Configure logging
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
ipv6_enabled = False
|
||||||
|
|
||||||
|
|
||||||
|
class MdnsConsole:
|
||||||
|
def __init__(self, command):
|
||||||
|
self.process = pexpect.spawn(command, encoding='utf-8')
|
||||||
|
self.process.logfile = open('mdns_interaction.log', 'w') # Log all interactions
|
||||||
|
self.process.expect('mdns> ', timeout=10)
|
||||||
|
|
||||||
|
def send_input(self, input_data):
|
||||||
|
logger.info(f'Sending to stdin: {input_data}')
|
||||||
|
self.process.sendline(input_data)
|
||||||
|
|
||||||
|
def get_output(self, expected_data):
|
||||||
|
logger.info(f'Expecting: {expected_data}')
|
||||||
|
self.process.expect(expected_data, timeout=10)
|
||||||
|
output = self.process.before.strip()
|
||||||
|
logger.info(f'Received from stdout: {output}')
|
||||||
|
return output
|
||||||
|
|
||||||
|
def terminate(self):
|
||||||
|
self.send_input('exit')
|
||||||
|
self.get_output('Exit')
|
||||||
|
self.process.wait()
|
||||||
|
self.process.close()
|
||||||
|
assert self.process.exitstatus == 0
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='module')
|
||||||
|
def mdns_console():
|
||||||
|
app = MdnsConsole('./build_linux_console/mdns_host.elf')
|
||||||
|
yield app
|
||||||
|
app.terminate()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='module')
|
||||||
|
def dig_app():
|
||||||
|
return DnsPythonWrapper()
|
||||||
|
|
||||||
|
|
||||||
|
def test_mdns_init(mdns_console, dig_app):
|
||||||
|
mdns_console.send_input('mdns_init -h hostname')
|
||||||
|
mdns_console.get_output('MDNS: Hostname: hostname')
|
||||||
|
dig_app.check_record('hostname.local', query_type='A', expected=True)
|
||||||
|
if ipv6_enabled:
|
||||||
|
dig_app.check_record('hostname.local', query_type='AAAA', expected=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_add_service(mdns_console, dig_app):
|
||||||
|
mdns_console.send_input('mdns_service_add _http _tcp 80 -i test_service')
|
||||||
|
mdns_console.get_output('MDNS: Service Instance: test_service')
|
||||||
|
dig_app.check_record('_http._tcp.local', query_type='PTR', expected=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_remove_service(mdns_console, dig_app):
|
||||||
|
mdns_console.send_input('mdns_service_remove _http _tcp')
|
||||||
|
dig_app.check_record('_http._tcp.local', query_type='PTR', expected=False)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
pytest.main(['-s', 'test_mdns.py'])
|
4
components/mdns/tests/host_test/sdkconfig.ci.app
Normal file
4
components/mdns/tests/host_test/sdkconfig.ci.app
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
CONFIG_IDF_TARGET="linux"
|
||||||
|
CONFIG_TEST_HOSTNAME="myesp"
|
||||||
|
CONFIG_MDNS_ENABLE_DEBUG_PRINTS=y
|
||||||
|
CONFIG_MDNS_RESPOND_REVERSE_QUERIES=y
|
4
components/mdns/tests/host_test/sdkconfig.ci.console
Normal file
4
components/mdns/tests/host_test/sdkconfig.ci.console
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
CONFIG_IDF_TARGET="linux"
|
||||||
|
CONFIG_ESP_EVENT_POST_FROM_ISR=n
|
||||||
|
CONFIG_MDNS_ENABLE_CONSOLE_CLI=y
|
||||||
|
CONFIG_TEST_CONSOLE=y
|
1
components/mdns/tests/host_test/sdkconfig.ci.target
Normal file
1
components/mdns/tests/host_test/sdkconfig.ci.target
Normal file
@ -0,0 +1 @@
|
|||||||
|
CONFIG_IDF_TARGET="esp32"
|
@ -1,9 +1,6 @@
|
|||||||
CONFIG_IDF_TARGET="linux"
|
CONFIG_TEST_NETIF_NAME="eth0"
|
||||||
|
CONFIG_ESP_EVENT_POST_FROM_ISR=n
|
||||||
CONFIG_MDNS_NETWORKING_SOCKET=y
|
CONFIG_MDNS_NETWORKING_SOCKET=y
|
||||||
CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES=y
|
CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES=y
|
||||||
CONFIG_TEST_NETIF_NAME="eth0"
|
|
||||||
CONFIG_TEST_HOSTNAME="myesp"
|
|
||||||
CONFIG_MDNS_PREDEF_NETIF_STA=n
|
CONFIG_MDNS_PREDEF_NETIF_STA=n
|
||||||
CONFIG_MDNS_PREDEF_NETIF_AP=n
|
CONFIG_MDNS_PREDEF_NETIF_AP=n
|
||||||
CONFIG_MDNS_ENABLE_DEBUG_PRINTS=y
|
|
||||||
CONFIG_MDNS_RESPOND_REVERSE_QUERIES=y
|
|
||||||
|
Reference in New Issue
Block a user