mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'host_test_websocket_transport2' into 'master'
feat(ws_transport): Added host test for websocket transport See merge request espressif/esp-idf!31022
This commit is contained in:
commit
ba55aed35c
@ -1,4 +1,4 @@
|
||||
idf_component_register(SRCS "test_socks_transport.cpp"
|
||||
idf_component_register(SRCS "test_socks_transport.cpp" "test_websocket_transport.cpp"
|
||||
REQUIRES tcp_transport mocked_transport
|
||||
INCLUDE_DIRS "$ENV{IDF_PATH}/tools"
|
||||
WHOLE_ARCHIVE)
|
||||
|
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include "fmt/core.h"
|
||||
#include "fmt/ranges.h"
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/matchers/catch_matchers_all.hpp>
|
||||
#include "esp_transport.h"
|
||||
#include "esp_transport_tcp.h"
|
||||
#include "esp_transport_ws.h"
|
||||
|
||||
#define WS_BUFFER_SIZE 1024
|
||||
|
||||
extern "C" {
|
||||
#include "Mockmock_transport.h"
|
||||
#include "Mocknetdb.h"
|
||||
#include "Mockesp_timer.h"
|
||||
#include "Mockesp_tls_crypto.h"
|
||||
|
||||
int lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
ssize_t lwip_recv(int s, void *mem, size_t len, int flags) {
|
||||
return WS_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
ssize_t lwip_send(int s, const void *data, size_t size, int flags) {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
using unique_transport = std::unique_ptr<std::remove_pointer_t<esp_transport_handle_t>, decltype(&esp_transport_destroy)>;
|
||||
|
||||
namespace {
|
||||
|
||||
std::string make_request() {
|
||||
const std::string sec_websocket_key = "x3JJHMbDL1EzLkh9GBhXDw=="; // Use a fixed key for testing
|
||||
std::string request;
|
||||
|
||||
request.append("GET / HTTP/1.1\r\n");
|
||||
request.append("Connection: Upgrade\r\n");
|
||||
request.append("Host: localhost:8080\r\n");
|
||||
request.append("User-Agent: ESP32 Websocket Client\r\n");
|
||||
request.append("Upgrade: websocket\r\n");
|
||||
request.append("Sec-WebSocket-Version: 13\r\n");
|
||||
request.append("Sec-WebSocket-Key: ").append(sec_websocket_key).append("\r\n");
|
||||
request.append("\r\n");
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
std::string make_response() {
|
||||
char response[WS_BUFFER_SIZE];
|
||||
int response_length = snprintf(response, WS_BUFFER_SIZE,
|
||||
"HTTP/1.1 101 Switching Protocols\r\n"
|
||||
"Upgrade: websocket\r\n"
|
||||
"Connection: Upgrade\r\n"
|
||||
"Sec-WebSocket-Accept:\r\n"
|
||||
"\r\n");
|
||||
// WebSocket frame header
|
||||
unsigned char ws_frame_header[] = {0x81, 0x04}; // First byte: FIN, RSV1-3, and opcode; Second byte: payload length
|
||||
unsigned char ws_payload[] = {'T', 'e', 's', 't'}; // Example payload
|
||||
|
||||
// Append the WebSocket frame header to the HTTP response
|
||||
std::memcpy(response + response_length, ws_frame_header, sizeof(ws_frame_header));
|
||||
response_length += sizeof(ws_frame_header);
|
||||
|
||||
// Append the payload to the HTTP response
|
||||
std::memcpy(response + response_length, ws_payload, sizeof(ws_payload));
|
||||
response_length += sizeof(ws_payload);
|
||||
return std::string(response, response_length);
|
||||
}
|
||||
|
||||
// Callback function for mock_write
|
||||
int mock_write_callback(esp_transport_handle_t transport, const char *request_sent, int len, int timeout_ms, int num_call) {
|
||||
// Assertions to validate the parameters
|
||||
assert(transport != nullptr); // Ensure the transport handle is not null
|
||||
assert(request_sent != nullptr); // Ensure the request_sent pointer is not null
|
||||
assert(len > 0); // Ensure the length of the request is greater than zero
|
||||
assert(timeout_ms > 0); // Ensure the timeout is greater than zero
|
||||
assert(num_call >= 0); // Ensure the number of calls is non-negative
|
||||
|
||||
// Create a string from the request_sent data
|
||||
std::string sent_request(request_sent, len);
|
||||
|
||||
// Generate the expected request
|
||||
std::string expected_request = make_request();
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
// Callback function for mock_read
|
||||
int mock_read_callback(esp_transport_handle_t transport, char *buffer, int len, int timeout_ms, int num_call) {
|
||||
std::string websocket_response = make_response();
|
||||
std::memcpy(buffer, websocket_response.data(), websocket_response.size());
|
||||
return websocket_response.size();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("WebSocket Transport Connection", "[websocket_transport]") {
|
||||
constexpr static auto timeout = 50;
|
||||
constexpr static auto port = 8080;
|
||||
constexpr static auto host = "localhost";
|
||||
// Initialize the parent handle
|
||||
unique_transport parent_handle{esp_transport_init(), esp_transport_destroy};
|
||||
REQUIRE(parent_handle);
|
||||
|
||||
// Set mock functions for parent handle
|
||||
esp_transport_set_func(parent_handle.get(), mock_connect, mock_read, mock_write, mock_close, mock_poll_read, mock_poll_write, mock_destroy);
|
||||
|
||||
unique_transport websocket_transport{esp_transport_ws_init(parent_handle.get()), esp_transport_destroy};
|
||||
REQUIRE(websocket_transport);
|
||||
|
||||
SECTION("Successful connection and read data") {
|
||||
fmt::print("Attempting to connect to WebSocket\n");
|
||||
esp_crypto_sha1_ExpectAnyArgsAndReturn(0);
|
||||
esp_crypto_base64_encode_ExpectAnyArgsAndReturn(0);
|
||||
|
||||
// Set the callback function for mock_write
|
||||
mock_write_Stub(mock_write_callback);
|
||||
mock_connect_ExpectAndReturn(parent_handle.get(), host, port, timeout, ESP_OK);
|
||||
// Set the callback function for mock_read
|
||||
mock_read_Stub(mock_read_callback);
|
||||
mock_poll_read_ExpectAnyArgsAndReturn(1);
|
||||
esp_crypto_base64_encode_ExpectAnyArgsAndReturn(0);
|
||||
mock_destroy_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
REQUIRE(esp_transport_connect(websocket_transport.get(), host, port, timeout) == 0);
|
||||
|
||||
char buffer[WS_BUFFER_SIZE];
|
||||
int read_len = esp_transport_read(websocket_transport.get(), buffer, WS_BUFFER_SIZE, timeout);
|
||||
fmt::print("Read result: {}\n", read_len);
|
||||
REQUIRE(read_len > 0); // Ensure data is read
|
||||
|
||||
std::string response(buffer, read_len);
|
||||
REQUIRE(response == "Test");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user