From aff571df2c7320005822dadccf8c170374144a30 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 6 Nov 2023 15:17:10 +0100 Subject: [PATCH] fix(modem): Added test-cases that exercise mode transitions --- .../test/host_test/main/test_modem.cpp | 87 ++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/components/esp_modem/test/host_test/main/test_modem.cpp b/components/esp_modem/test/host_test/main/test_modem.cpp index 4a238f5bc..1a27cc59f 100644 --- a/components/esp_modem/test/host_test/main/test_modem.cpp +++ b/components/esp_modem/test/host_test/main/test_modem.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -247,3 +247,88 @@ TEST_CASE("Test CMUX protocol by injecting payloads", "[esp_modem]") CHECK(ret == command_result::OK); } } + +TEST_CASE("Command and Data mode transitions", "[esp_modem][transitions]") +{ + auto term = std::make_unique(); + auto loopback = term.get(); + auto dte = std::make_shared(std::move(term)); + CHECK(term == nullptr); + + esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("APN"); + esp_netif_t netif{}; + auto dce = create_SIM7600_dce(&dce_config, dte, &netif); + CHECK(dce != nullptr); + + // UNDEF -> CMD (OK) + uint8_t resp[] = "DISCONNECTED\n"; + loopback->inject(&resp[0], sizeof(resp), sizeof(resp), /* 10ms before injecting reply */100, 0); + loopback->write(nullptr, 0); /* this triggers sending the injected response */ + CHECK(dce->set_mode(esp_modem::modem_mode::COMMAND_MODE) == true); + loopback->inject(nullptr, 0, 0, 0, 0); /* reset injection, use synchronous replies now */ + // CMD -> CMD (Fail) + CHECK(dce->set_mode(esp_modem::modem_mode::COMMAND_MODE) == false); + + // Forcing transition to CMD (via UNDEF) + // CMD -> UNDEF (OK) + CHECK(dce->set_mode(esp_modem::modem_mode::UNDEF) == true); + // UNDEF -> CMD (OK) + CHECK(dce->set_mode(esp_modem::modem_mode::COMMAND_MODE) == true); + + // CMD -> DATA (OK) + CHECK(dce->set_mode(esp_modem::modem_mode::DATA_MODE) == true); + // DATA -> CMD (OK) + CHECK(dce->set_mode(esp_modem::modem_mode::COMMAND_MODE) == true); +} + +TEST_CASE("CMUX mode transitions", "[esp_modem][transitions]") +{ + auto term = std::make_unique(); + auto dte = std::make_shared(std::move(term)); + CHECK(term == nullptr); + + esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("APN"); + esp_netif_t netif{}; + auto dce = create_SIM7600_dce(&dce_config, dte, &netif); + CHECK(dce != nullptr); + // UNDEF -> CMUX (OK) + CHECK(dce->set_mode(esp_modem::modem_mode::CMUX_MODE) == true); + // CMUX -> DATA (Fail) + CHECK(dce->set_mode(esp_modem::modem_mode::DATA_MODE) == false); + // CMUX back -> CMD (OK) + CHECK(dce->set_mode(esp_modem::modem_mode::COMMAND_MODE) == true); +} + +TEST_CASE("CMUX manual mode transitions", "[esp_modem][transitions]") +{ + auto term = std::make_unique(); + auto dte = std::make_shared(std::move(term)); + CHECK(term == nullptr); + + esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("APN"); + esp_netif_t netif{}; + auto dce = create_SIM7600_dce(&dce_config, dte, &netif); + CHECK(dce != nullptr); + + // Happy flow transitions of Manual CMUX transitions + CHECK(dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_MODE) == true); + CHECK(dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_EXIT) == true); + CHECK(dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_MODE) == true); + CHECK(dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_SWAP) == true); + CHECK(dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_DATA) == true); + // Cannot test CMUX_MANUAL_DATA -> CMUX_MANUAL_COMMAND with our mocked terminal for now + CHECK(dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_EXIT) == true); + + // Check some out of order manual transitions, most of them are allowed, + // but some fail as modem layers report issues with specific steps + CHECK(dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_SWAP) == false); // cannot go directly to SWAP + CHECK(dce->set_mode(esp_modem::modem_mode::UNDEF) == true); + CHECK(dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_SWAP) == true); // can go via UNDEF + CHECK(dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_EXIT) == false); // EXIT is allowed, but CMUX terms don't exist + CHECK(dce->set_mode(esp_modem::modem_mode::UNDEF) == true); + CHECK(dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_MODE) == true); // Enter CMUX (via UNDEF) + CHECK(dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_DATA) == true); // Go directly to DATA mode + CHECK(dce->set_mode(esp_modem::modem_mode::CMUX_MANUAL_EXIT) == true); // Exit CMUX + CHECK(dce->set_mode(esp_modem::modem_mode::UNDEF) == true); // Succeeds from any state + +}