mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-05 21:54:33 +02:00
Merge branch 'feature/add_protocol_http_example_tests' into 'master'
Feature/add protocol http example tests Closes IDF-1154 See merge request espressif/esp-idf!11967
This commit is contained in:
72
examples/protocols/http2_request/example_test.py
Normal file
72
examples/protocols/http2_request/example_test.py
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
import http.client
|
||||||
|
import os
|
||||||
|
|
||||||
|
import tiny_test_fw
|
||||||
|
import ttfw_idf
|
||||||
|
from tiny_test_fw import Utility
|
||||||
|
|
||||||
|
HTTP_OK = 200
|
||||||
|
TEST_SERVER = 'http2.golang.org'
|
||||||
|
|
||||||
|
|
||||||
|
def is_test_server_available(): # type: () -> bool
|
||||||
|
# 443 - default https port
|
||||||
|
conn = http.client.HTTPSConnection(TEST_SERVER, 443, timeout=10)
|
||||||
|
conn.request('GET', '/')
|
||||||
|
resp = conn.getresponse()
|
||||||
|
conn.close()
|
||||||
|
if resp.status == HTTP_OK:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@ttfw_idf.idf_example_test(env_tag='Example_EthKitV1')
|
||||||
|
def test_examples_protocol_http2_request(env, extra_data): # type: (tiny_test_fw.Env.Env, None) -> None # pylint: disable=unused-argument
|
||||||
|
"""
|
||||||
|
steps: |
|
||||||
|
1. join AP
|
||||||
|
2. connect to http2.golang.org
|
||||||
|
3. send http2 request
|
||||||
|
4. send http2 put response
|
||||||
|
"""
|
||||||
|
dut1 = env.get_dut('http2_request', 'examples/protocols/http2_request', dut_class=ttfw_idf.ESP32DUT)
|
||||||
|
# check and log bin size
|
||||||
|
binary_file = os.path.join(dut1.app.binary_path, 'http2-request.bin')
|
||||||
|
bin_size = os.path.getsize(binary_file)
|
||||||
|
ttfw_idf.log_performance('http2_request_bin_size', '{}KB'.format(bin_size // 1024))
|
||||||
|
# start the test
|
||||||
|
# check if test server is avilable
|
||||||
|
test_server_available = is_test_server_available()
|
||||||
|
# Skip the test if the server test server (http2.golang.org) is not available at the moment.
|
||||||
|
if test_server_available:
|
||||||
|
dut1.start_app()
|
||||||
|
# check for connection
|
||||||
|
dut1.expect('Connection done', timeout=30)
|
||||||
|
# check for echo response
|
||||||
|
dut1.expect('[echo-response] HELLO WORLD', timeout=30)
|
||||||
|
dut1.expect('[echo-response] Frame fully received')
|
||||||
|
dut1.expect('[echo-response] Stream Closed')
|
||||||
|
# check for get response
|
||||||
|
dut1.expect('[get-response] Frame fully received')
|
||||||
|
else:
|
||||||
|
Utility.console_log('test server \"{0}\" is not available at the moment.\nSkipping the test with status = success.'.format(TEST_SERVER))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_examples_protocol_http2_request() # pylint: disable=no-value-for-parameter
|
11
examples/protocols/http2_request/sdkconfig.ci
Normal file
11
examples/protocols/http2_request/sdkconfig.ci
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
CONFIG_ESP32_SPIRAM_SUPPORT=y
|
||||||
|
CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
||||||
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
|
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
||||||
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
|
||||||
|
CONFIG_EXAMPLE_CONNECT_IPV6=y
|
52
examples/protocols/http_request/example_test.py
Normal file
52
examples/protocols/http_request/example_test.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
import tiny_test_fw
|
||||||
|
import ttfw_idf
|
||||||
|
|
||||||
|
|
||||||
|
@ttfw_idf.idf_example_test(env_tag='Example_EthKitV1')
|
||||||
|
def test_examples_protocol_http_request(env, extra_data): # type: (tiny_test_fw.Env.Env, None) -> None # pylint: disable=unused-argument
|
||||||
|
"""
|
||||||
|
steps: |
|
||||||
|
1. join AP
|
||||||
|
2. connect to example.com
|
||||||
|
3. check conneciton success
|
||||||
|
"""
|
||||||
|
dut1 = env.get_dut('http_request', 'examples/protocols/http_request', dut_class=ttfw_idf.ESP32DUT)
|
||||||
|
# check and log bin size
|
||||||
|
binary_file = os.path.join(dut1.app.binary_path, 'http-request.bin')
|
||||||
|
bin_size = os.path.getsize(binary_file)
|
||||||
|
ttfw_idf.log_performance('http_request_bin_size', '{}KB'.format(bin_size // 1024))
|
||||||
|
# start test
|
||||||
|
dut1.start_app()
|
||||||
|
dut1.expect(re.compile(r'DNS lookup succeeded.'))
|
||||||
|
# check if connected or not
|
||||||
|
dut1.expect(' ... connected', timeout=60)
|
||||||
|
dut1.expect(' ... socket send success')
|
||||||
|
dut1.expect(' ... set socket receiving timeout success')
|
||||||
|
# check server response
|
||||||
|
dut1.expect(re.compile(r'HTTP/1.0 200 OK'))
|
||||||
|
# read from the socket completed
|
||||||
|
dut1.expect('... done reading from socket. Last read return=0 errno=128')
|
||||||
|
dut1.expect(re.compile(r'(\d)...'))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_examples_protocol_http_request() # pylint: disable=no-value-for-parameter
|
9
examples/protocols/http_request/sdkconfig.ci
Normal file
9
examples/protocols/http_request/sdkconfig.ci
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
|
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
||||||
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
|
||||||
|
CONFIG_EXAMPLE_CONNECT_IPV6=y
|
@@ -0,0 +1,147 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import http.client
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
import tiny_test_fw
|
||||||
|
import ttfw_idf
|
||||||
|
from idf_http_server_test import adder as client
|
||||||
|
from tiny_test_fw import Utility
|
||||||
|
|
||||||
|
|
||||||
|
@ttfw_idf.idf_example_test(env_tag='Example_WIFI')
|
||||||
|
def test_examples_protocol_http_server_file_serving(env, extra_data): # type: (tiny_test_fw.Env.Env, None) -> None # pylint: disable=unused-argument
|
||||||
|
# Acquire DUT
|
||||||
|
dut1 = env.get_dut('http file_serving', 'examples/protocols/http_server/file_serving', dut_class=ttfw_idf.ESP32DUT)
|
||||||
|
|
||||||
|
# Get binary file
|
||||||
|
binary_file = os.path.join(dut1.app.binary_path, 'file_server.bin')
|
||||||
|
bin_size = os.path.getsize(binary_file)
|
||||||
|
ttfw_idf.log_performance('file_server_bin_size', '{}KB'.format(bin_size // 1024))
|
||||||
|
Utility.console_log('Erasing the flash on the chip')
|
||||||
|
# erase the flash
|
||||||
|
dut1.erase_flash()
|
||||||
|
# Upload binary and start testing
|
||||||
|
Utility.console_log('Starting http file serving simple test app')
|
||||||
|
dut1.start_app()
|
||||||
|
|
||||||
|
# Parse IP address of STA
|
||||||
|
Utility.console_log('Waiting to connect with AP')
|
||||||
|
got_ip = dut1.expect(re.compile(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)'), timeout=30)[0]
|
||||||
|
# Expected logs
|
||||||
|
dut1.expect('Initializing SPIFFS', timeout=30)
|
||||||
|
got_port = dut1.expect(re.compile(r"Starting HTTP Server on port: '(\d+)'"), timeout=30)[0]
|
||||||
|
Utility.console_log('Got IP : ' + got_ip)
|
||||||
|
Utility.console_log('Got Port : ' + got_port)
|
||||||
|
|
||||||
|
# Run test script
|
||||||
|
conn = client.start_session(got_ip, got_port)
|
||||||
|
|
||||||
|
# upload a file onto the server
|
||||||
|
upload_data = 'Test data to be sent to the server'
|
||||||
|
|
||||||
|
upload_file_name = 'example.txt'
|
||||||
|
upload_file_hash = hashlib.md5(upload_data.encode('UTF-8'))
|
||||||
|
upload_file_digest = upload_file_hash.digest()
|
||||||
|
Utility.console_log('\nTesting the uploading of file on the file server')
|
||||||
|
client.postreq(conn, '/upload/' + str(upload_file_name), upload_data)
|
||||||
|
|
||||||
|
try:
|
||||||
|
dut1.expect('File reception complete', timeout=10)
|
||||||
|
except Exception:
|
||||||
|
Utility.console_log('Failed the test to upload file on the file server')
|
||||||
|
raise
|
||||||
|
Utility.console_log('Passed the test to uploaded file on the file server')
|
||||||
|
|
||||||
|
# Download the uploaded file from the file server
|
||||||
|
Utility.console_log("\nTesting for Download of \"existing\" file from the file server")
|
||||||
|
|
||||||
|
download_data = client.getreq(conn, '/' + str(upload_file_name))
|
||||||
|
|
||||||
|
try:
|
||||||
|
dut1.expect('File sending complete', timeout=10)
|
||||||
|
except Exception:
|
||||||
|
Utility.console_log('Failed the test to download existing file from the file server')
|
||||||
|
raise
|
||||||
|
Utility.console_log('Passed the test to downloaded existing file from the file server')
|
||||||
|
|
||||||
|
download_file_hash = hashlib.md5(download_data)
|
||||||
|
download_file_digest = download_file_hash.digest()
|
||||||
|
|
||||||
|
if download_file_digest != upload_file_digest:
|
||||||
|
raise RuntimeError('The md5 hash of the downloaded file does not match with that of the uploaded file')
|
||||||
|
|
||||||
|
# Upload existing file on the file server
|
||||||
|
Utility.console_log("\nTesting the upload of \"already existing\" file on the file server")
|
||||||
|
client.postreq(conn, '/upload/' + str(upload_file_name), data=None)
|
||||||
|
try:
|
||||||
|
dut1.expect('File already exists : /spiffs/' + str(upload_file_name), timeout=10)
|
||||||
|
except Exception:
|
||||||
|
Utility.console_log('Failed the test for uploading existing file on the file server')
|
||||||
|
raise
|
||||||
|
Utility.console_log('Passed the test for uploading existing file on the file server')
|
||||||
|
# Previous URI was an invalid URI so the server should have closed the connection.
|
||||||
|
# Trying to send request to the server
|
||||||
|
try:
|
||||||
|
client.getreq(conn, '/')
|
||||||
|
except http.client.RemoteDisconnected:
|
||||||
|
# It is correct behavior that the connection was closed by the server
|
||||||
|
pass
|
||||||
|
except Exception:
|
||||||
|
Utility.console_log('Connection was not closed successfully by the server after last invalid URI')
|
||||||
|
raise
|
||||||
|
|
||||||
|
conn = client.start_session(got_ip, got_port)
|
||||||
|
# Delete the existing file from the file server
|
||||||
|
Utility.console_log("\nTesting the deletion of \"existing\" file on the file server")
|
||||||
|
client.postreq(conn, '/delete/' + str(upload_file_name), data=None)
|
||||||
|
try:
|
||||||
|
dut1.expect('Deleting file : /' + str(upload_file_name), timeout=10)
|
||||||
|
except Exception:
|
||||||
|
Utility.console_log('Failed the test for deletion of existing file on the file server')
|
||||||
|
raise
|
||||||
|
Utility.console_log('Passed the test for deletion of existing file on the file server')
|
||||||
|
|
||||||
|
conn = client.start_session(got_ip, got_port)
|
||||||
|
# Try to delete non existing file from the file server
|
||||||
|
Utility.console_log("\nTesting the deletion of \"non existing\" file on the file server")
|
||||||
|
client.postreq(conn, '/delete/' + str(upload_file_name), data=None)
|
||||||
|
try:
|
||||||
|
dut1.expect('File does not exist : /' + str(upload_file_name), timeout=10)
|
||||||
|
except Exception:
|
||||||
|
Utility.console_log('Failed the test for deleting non existing file on the file server')
|
||||||
|
raise
|
||||||
|
Utility.console_log('Passed the test for deleting non existing file on the file server')
|
||||||
|
|
||||||
|
conn = client.start_session(got_ip, got_port)
|
||||||
|
# Try to download non existing file from the file server
|
||||||
|
Utility.console_log("\nTesting for Download of \"non existing\" file from the file server")
|
||||||
|
|
||||||
|
download_data = client.getreq(conn, '/' + str(upload_file_name))
|
||||||
|
|
||||||
|
try:
|
||||||
|
dut1.expect('Failed to stat file : /spiffs/' + str(upload_file_name), timeout=10)
|
||||||
|
except Exception:
|
||||||
|
Utility.console_log('Failed the test to download non existing file from the file server')
|
||||||
|
raise
|
||||||
|
Utility.console_log('Passed the test to downloaded non existing file from the file server')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_examples_protocol_http_server_file_serving() # pylint: disable=no-value-for-parameter
|
@@ -475,7 +475,7 @@ esp_err_t start_file_server(const char *base_path)
|
|||||||
* target URIs which match the wildcard scheme */
|
* target URIs which match the wildcard scheme */
|
||||||
config.uri_match_fn = httpd_uri_match_wildcard;
|
config.uri_match_fn = httpd_uri_match_wildcard;
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Starting HTTP Server");
|
ESP_LOGI(TAG, "Starting HTTP Server on port: '%d'", config.server_port);
|
||||||
if (httpd_start(&server, &config) != ESP_OK) {
|
if (httpd_start(&server, &config) != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Failed to start file server!");
|
ESP_LOGE(TAG, "Failed to start file server!");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
CONFIG_EXAMPLE_MOUNT_SD_CARD=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_EXAMPLE_FORMAT_IF_MOUNT_SDCARD_FAILED=y
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv"
|
||||||
CONFIG_EXAMPLE_USE_SDMMC_HOST=y
|
CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv"
|
||||||
|
@@ -0,0 +1,3 @@
|
|||||||
|
CONFIG_EXAMPLE_MOUNT_SD_CARD=y
|
||||||
|
CONFIG_EXAMPLE_FORMAT_IF_MOUNT_SDCARD_FAILED=y
|
||||||
|
CONFIG_EXAMPLE_USE_SDMMC_HOST=y
|
@@ -72,6 +72,7 @@ static esp_err_t echo_handler(httpd_req_t *req)
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
httpd_ws_frame_t ws_pkt;
|
httpd_ws_frame_t ws_pkt;
|
||||||
|
uint8_t *buf = NULL;
|
||||||
memset(&ws_pkt, 0, sizeof(httpd_ws_frame_t));
|
memset(&ws_pkt, 0, sizeof(httpd_ws_frame_t));
|
||||||
ws_pkt.type = HTTPD_WS_TYPE_TEXT;
|
ws_pkt.type = HTTPD_WS_TYPE_TEXT;
|
||||||
/* Set max_len = 0 to get the frame len */
|
/* Set max_len = 0 to get the frame len */
|
||||||
@@ -81,8 +82,9 @@ static esp_err_t echo_handler(httpd_req_t *req)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
ESP_LOGI(TAG, "frame len is %d", ws_pkt.len);
|
ESP_LOGI(TAG, "frame len is %d", ws_pkt.len);
|
||||||
|
if (ws_pkt.len) {
|
||||||
/* ws_pkt.len + 1 is for NULL termination as we are expecting a string */
|
/* ws_pkt.len + 1 is for NULL termination as we are expecting a string */
|
||||||
uint8_t *buf = calloc(1, ws_pkt.len + 1);
|
buf = calloc(1, ws_pkt.len + 1);
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
ESP_LOGE(TAG, "Failed to calloc memory for buf");
|
ESP_LOGE(TAG, "Failed to calloc memory for buf");
|
||||||
return ESP_ERR_NO_MEM;
|
return ESP_ERR_NO_MEM;
|
||||||
@@ -92,14 +94,15 @@ static esp_err_t echo_handler(httpd_req_t *req)
|
|||||||
ret = httpd_ws_recv_frame(req, &ws_pkt, ws_pkt.len);
|
ret = httpd_ws_recv_frame(req, &ws_pkt, ws_pkt.len);
|
||||||
if (ret != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "httpd_ws_recv_frame failed with %d", ret);
|
ESP_LOGE(TAG, "httpd_ws_recv_frame failed with %d", ret);
|
||||||
|
free(buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
ESP_LOGI(TAG, "Got packet with message: %s", ws_pkt.payload);
|
ESP_LOGI(TAG, "Got packet with message: %s", ws_pkt.payload);
|
||||||
|
}
|
||||||
ESP_LOGI(TAG, "Packet type: %d", ws_pkt.type);
|
ESP_LOGI(TAG, "Packet type: %d", ws_pkt.type);
|
||||||
if (ws_pkt.type == HTTPD_WS_TYPE_TEXT &&
|
if (ws_pkt.type == HTTPD_WS_TYPE_TEXT &&
|
||||||
strcmp((char*)ws_pkt.payload,"Trigger async") == 0) {
|
strcmp((char*)ws_pkt.payload,"Trigger async") == 0) {
|
||||||
free(buf);
|
free(buf);
|
||||||
buf = NULL;
|
|
||||||
return trigger_async_send(req->handle, req);
|
return trigger_async_send(req->handle, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +111,6 @@ static esp_err_t echo_handler(httpd_req_t *req)
|
|||||||
ESP_LOGE(TAG, "httpd_ws_send_frame failed with %d", ret);
|
ESP_LOGE(TAG, "httpd_ws_send_frame failed with %d", ret);
|
||||||
}
|
}
|
||||||
free(buf);
|
free(buf);
|
||||||
buf = NULL;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
51
examples/protocols/https_mbedtls/example_test.py
Normal file
51
examples/protocols/https_mbedtls/example_test.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
import tiny_test_fw
|
||||||
|
import ttfw_idf
|
||||||
|
from tiny_test_fw import Utility
|
||||||
|
|
||||||
|
|
||||||
|
@ttfw_idf.idf_example_test(env_tag='Example_EthKitV1')
|
||||||
|
def test_examples_protocol_https_mbedtls(env, extra_data): # type: (tiny_test_fw.Env.Env, None) -> None # pylint: disable=unused-argument
|
||||||
|
"""
|
||||||
|
steps: |
|
||||||
|
1. join AP
|
||||||
|
2. connect to www.howsmyssl.com:443
|
||||||
|
3. send http request
|
||||||
|
"""
|
||||||
|
dut1 = env.get_dut('https_mbedtls', 'examples/protocols/https_mbedtls', dut_class=ttfw_idf.ESP32DUT)
|
||||||
|
# check and log bin size
|
||||||
|
binary_file = os.path.join(dut1.app.binary_path, 'https-mbedtls.bin')
|
||||||
|
bin_size = os.path.getsize(binary_file)
|
||||||
|
ttfw_idf.log_performance('https_mbedtls_bin_size', '{}KB'.format(bin_size // 1024))
|
||||||
|
# start test
|
||||||
|
dut1.start_app()
|
||||||
|
dut1.expect('Connected.', timeout=30)
|
||||||
|
Utility.console_log('TCP connection established with the server\n performing SSL/TLS handshake')
|
||||||
|
dut1.expect('Performing the SSL/TLS handshake...')
|
||||||
|
dut1.expect('Certificate verified.')
|
||||||
|
Utility.console_log('SSL/TLS handshake successful')
|
||||||
|
dut1.expect('Writing HTTP request...')
|
||||||
|
dut1.expect('Reading HTTP response...')
|
||||||
|
dut1.expect(re.compile(r'Completed (\d) requests'))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_examples_protocol_https_mbedtls() # pylint: disable=no-value-for-parameter
|
11
examples/protocols/https_mbedtls/sdkconfig.ci
Normal file
11
examples/protocols/https_mbedtls/sdkconfig.ci
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
CONFIG_ESP32_SPIRAM_SUPPORT=y
|
||||||
|
CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
||||||
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
|
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
||||||
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
|
||||||
|
CONFIG_EXAMPLE_CONNECT_IPV6=y
|
98
examples/protocols/https_server/simple/example_test.py
Normal file
98
examples/protocols/https_server/simple/example_test.py
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
import http.client
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import ssl
|
||||||
|
|
||||||
|
import tiny_test_fw
|
||||||
|
import ttfw_idf
|
||||||
|
from tiny_test_fw import Utility
|
||||||
|
|
||||||
|
server_cert_pem = '-----BEGIN CERTIFICATE-----\n'\
|
||||||
|
'MIIDKzCCAhOgAwIBAgIUBxM3WJf2bP12kAfqhmhhjZWv0ukwDQYJKoZIhvcNAQEL\n'\
|
||||||
|
'BQAwJTEjMCEGA1UEAwwaRVNQMzIgSFRUUFMgc2VydmVyIGV4YW1wbGUwHhcNMTgx\n'\
|
||||||
|
'MDE3MTEzMjU3WhcNMjgxMDE0MTEzMjU3WjAlMSMwIQYDVQQDDBpFU1AzMiBIVFRQ\n'\
|
||||||
|
'UyBzZXJ2ZXIgZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n'\
|
||||||
|
'ALBint6nP77RCQcmKgwPtTsGK0uClxg+LwKJ3WXuye3oqnnjqJCwMEneXzGdG09T\n'\
|
||||||
|
'sA0SyNPwrEgebLCH80an3gWU4pHDdqGHfJQa2jBL290e/5L5MB+6PTs2NKcojK/k\n'\
|
||||||
|
'qcZkn58MWXhDW1NpAnJtjVniK2Ksvr/YIYSbyD+JiEs0MGxEx+kOl9d7hRHJaIzd\n'\
|
||||||
|
'GF/vO2pl295v1qXekAlkgNMtYIVAjUy9CMpqaQBCQRL+BmPSJRkXBsYk8GPnieS4\n'\
|
||||||
|
'sUsp53DsNvCCtWDT6fd9D1v+BB6nDk/FCPKhtjYOwOAZlX4wWNSZpRNr5dfrxKsb\n'\
|
||||||
|
'jAn4PCuR2akdF4G8WLUeDWECAwEAAaNTMFEwHQYDVR0OBBYEFMnmdJKOEepXrHI/\n'\
|
||||||
|
'ivM6mVqJgAX8MB8GA1UdIwQYMBaAFMnmdJKOEepXrHI/ivM6mVqJgAX8MA8GA1Ud\n'\
|
||||||
|
'EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADiXIGEkSsN0SLSfCF1VNWO3\n'\
|
||||||
|
'emBurfOcDq4EGEaxRKAU0814VEmU87btIDx80+z5Dbf+GGHCPrY7odIkxGNn0DJY\n'\
|
||||||
|
'W1WcF+DOcbiWoUN6DTkAML0SMnp8aGj9ffx3x+qoggT+vGdWVVA4pgwqZT7Ybntx\n'\
|
||||||
|
'bkzcNFW0sqmCv4IN1t4w6L0A87ZwsNwVpre/j6uyBw7s8YoJHDLRFT6g7qgn0tcN\n'\
|
||||||
|
'ZufhNISvgWCVJQy/SZjNBHSpnIdCUSJAeTY2mkM4sGxY0Widk8LnjydxZUSxC3Nl\n'\
|
||||||
|
'hb6pnMh3jRq4h0+5CZielA4/a+TdrNPv/qok67ot/XJdY3qHCCd8O2b14OVq9jo=\n'\
|
||||||
|
'-----END CERTIFICATE-----\n'
|
||||||
|
|
||||||
|
success_response = '<h1>Hello Secure World!</h1>'
|
||||||
|
|
||||||
|
|
||||||
|
@ttfw_idf.idf_example_test(env_tag='Example_WIFI')
|
||||||
|
def test_examples_protocol_https_server_simple(env, extra_data): # type: (tiny_test_fw.Env.Env, None) -> None # pylint: disable=unused-argument
|
||||||
|
"""
|
||||||
|
steps: |
|
||||||
|
1. join AP
|
||||||
|
2. connect to www.howsmyssl.com:443
|
||||||
|
3. send http request
|
||||||
|
"""
|
||||||
|
dut1 = env.get_dut('https_server_simple', 'examples/protocols/https_server/simple', dut_class=ttfw_idf.ESP32DUT)
|
||||||
|
# check and log bin size
|
||||||
|
binary_file = os.path.join(dut1.app.binary_path, 'https_server.bin')
|
||||||
|
bin_size = os.path.getsize(binary_file)
|
||||||
|
ttfw_idf.log_performance('https_server_simple_bin_size', '{}KB'.format(bin_size // 1024))
|
||||||
|
# start test
|
||||||
|
dut1.start_app()
|
||||||
|
# Parse IP address and port of the server
|
||||||
|
dut1.expect(re.compile(r'Starting server'))
|
||||||
|
got_port = dut1.expect(re.compile(r'Server listening on port (\d+)'), timeout=30)[0]
|
||||||
|
Utility.console_log('Waiting to connect with AP')
|
||||||
|
|
||||||
|
got_ip = dut1.expect(re.compile(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)'), timeout=30)[0]
|
||||||
|
# Expected logs
|
||||||
|
|
||||||
|
Utility.console_log('Got IP : ' + got_ip)
|
||||||
|
Utility.console_log('Got Port : ' + got_port)
|
||||||
|
|
||||||
|
Utility.console_log('Performing GET request over an SSL connection with the server')
|
||||||
|
|
||||||
|
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
|
||||||
|
ssl_context.verify_mode = ssl.CERT_REQUIRED
|
||||||
|
ssl_context.check_hostname = False
|
||||||
|
ssl_context.load_verify_locations(cadata=server_cert_pem)
|
||||||
|
conn = http.client.HTTPSConnection(got_ip, got_port, context=ssl_context)
|
||||||
|
Utility.console_log('Performing SSL handshake with the server')
|
||||||
|
conn.request('GET','/')
|
||||||
|
resp = conn.getresponse()
|
||||||
|
dut1.expect('performing session handshake')
|
||||||
|
got_resp = resp.read().decode('utf-8')
|
||||||
|
# Close the connection
|
||||||
|
if got_resp != success_response:
|
||||||
|
Utility.console_log('Response obtained does not match with correct response')
|
||||||
|
raise RuntimeError('Failed to test SSL connection')
|
||||||
|
|
||||||
|
Utility.console_log('Correct response obtained')
|
||||||
|
Utility.console_log('SSL connection test successful\nClosing the connection')
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_examples_protocol_https_server_simple() # pylint: disable=no-value-for-parameter
|
@@ -38,6 +38,7 @@ static esp_err_t ws_handler(httpd_req_t *req)
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
httpd_ws_frame_t ws_pkt;
|
httpd_ws_frame_t ws_pkt;
|
||||||
|
uint8_t *buf = NULL;
|
||||||
memset(&ws_pkt, 0, sizeof(httpd_ws_frame_t));
|
memset(&ws_pkt, 0, sizeof(httpd_ws_frame_t));
|
||||||
|
|
||||||
// First receive the full ws message
|
// First receive the full ws message
|
||||||
@@ -48,8 +49,9 @@ static esp_err_t ws_handler(httpd_req_t *req)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
ESP_LOGI(TAG, "frame len is %d", ws_pkt.len);
|
ESP_LOGI(TAG, "frame len is %d", ws_pkt.len);
|
||||||
|
if (ws_pkt.len) {
|
||||||
/* ws_pkt.len + 1 is for NULL termination as we are expecting a string */
|
/* ws_pkt.len + 1 is for NULL termination as we are expecting a string */
|
||||||
uint8_t *buf = calloc(1, ws_pkt.len + 1);
|
buf = calloc(1, ws_pkt.len + 1);
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
ESP_LOGE(TAG, "Failed to calloc memory for buf");
|
ESP_LOGE(TAG, "Failed to calloc memory for buf");
|
||||||
return ESP_ERR_NO_MEM;
|
return ESP_ERR_NO_MEM;
|
||||||
@@ -59,14 +61,14 @@ static esp_err_t ws_handler(httpd_req_t *req)
|
|||||||
ret = httpd_ws_recv_frame(req, &ws_pkt, ws_pkt.len);
|
ret = httpd_ws_recv_frame(req, &ws_pkt, ws_pkt.len);
|
||||||
if (ret != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "httpd_ws_recv_frame failed with %d", ret);
|
ESP_LOGE(TAG, "httpd_ws_recv_frame failed with %d", ret);
|
||||||
|
free(buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// If it was a PONG, update the keep-alive
|
// If it was a PONG, update the keep-alive
|
||||||
if (ws_pkt.type == HTTPD_WS_TYPE_PONG) {
|
if (ws_pkt.type == HTTPD_WS_TYPE_PONG) {
|
||||||
ESP_LOGD(TAG, "Received PONG message");
|
ESP_LOGD(TAG, "Received PONG message");
|
||||||
free(buf);
|
free(buf);
|
||||||
buf = NULL;
|
|
||||||
return wss_keep_alive_client_is_active(httpd_get_global_user_ctx(req->handle),
|
return wss_keep_alive_client_is_active(httpd_get_global_user_ctx(req->handle),
|
||||||
httpd_req_to_sockfd(req));
|
httpd_req_to_sockfd(req));
|
||||||
|
|
||||||
@@ -80,11 +82,9 @@ static esp_err_t ws_handler(httpd_req_t *req)
|
|||||||
ESP_LOGI(TAG, "ws_handler: httpd_handle_t=%p, sockfd=%d, client_info:%d", req->handle,
|
ESP_LOGI(TAG, "ws_handler: httpd_handle_t=%p, sockfd=%d, client_info:%d", req->handle,
|
||||||
httpd_req_to_sockfd(req), httpd_ws_get_fd_info(req->handle, httpd_req_to_sockfd(req)));
|
httpd_req_to_sockfd(req), httpd_ws_get_fd_info(req->handle, httpd_req_to_sockfd(req)));
|
||||||
free(buf);
|
free(buf);
|
||||||
buf = NULL;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
free(buf);
|
free(buf);
|
||||||
buf = NULL;
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,192 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from __future__ import division, print_function, unicode_literals
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
from types import TracebackType
|
||||||
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
import tiny_test_fw
|
||||||
|
import ttfw_idf
|
||||||
|
import websocket
|
||||||
|
from tiny_test_fw import Utility
|
||||||
|
|
||||||
|
OPCODE_TEXT = 0x1
|
||||||
|
OPCODE_BIN = 0x2
|
||||||
|
OPCODE_PING = 0x9
|
||||||
|
OPCODE_PONG = 0xa
|
||||||
|
CORRECT_ASYNC_DATA = 'Hello client'
|
||||||
|
|
||||||
|
|
||||||
|
class WsClient:
|
||||||
|
def __init__(self, ip, port, ca_file): # type: (str, int, str) -> None
|
||||||
|
self.port = port
|
||||||
|
self.ip = ip
|
||||||
|
sslopt = {'ca_certs':ca_file, 'check_hostname': False}
|
||||||
|
self.ws = websocket.WebSocket(sslopt=sslopt)
|
||||||
|
# Set timeout to 10 seconds to avoid conection failure at the time of handshake
|
||||||
|
self.ws.settimeout(10)
|
||||||
|
|
||||||
|
def __enter__(self): # type: ignore
|
||||||
|
self.ws.connect('wss://{}:{}/ws'.format(self.ip, self.port))
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_value, traceback): # type: (type, RuntimeError, TracebackType) -> None
|
||||||
|
self.ws.close()
|
||||||
|
|
||||||
|
def read(self): # type: () -> Any
|
||||||
|
return self.ws.recv_data(control_frame=True)
|
||||||
|
|
||||||
|
def write(self, data, opcode=OPCODE_TEXT): # type: (str, int) -> Any
|
||||||
|
if opcode == OPCODE_PING:
|
||||||
|
return self.ws.ping(data)
|
||||||
|
if opcode == OPCODE_PONG:
|
||||||
|
return self.ws.pong(data)
|
||||||
|
return self.ws.send(data)
|
||||||
|
|
||||||
|
|
||||||
|
class wss_client_thread(threading.Thread):
|
||||||
|
def __init__(self, ip, port, ca_file): # type: (str, int, str) -> None
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
self.ip = ip
|
||||||
|
self.port = port
|
||||||
|
self.ca_file = ca_file
|
||||||
|
self.start_time = time.time()
|
||||||
|
self.exc = None
|
||||||
|
self.data = 'Espressif'
|
||||||
|
self.async_response = False
|
||||||
|
|
||||||
|
def run(self): # type: () -> None
|
||||||
|
with WsClient(self.ip, self.port, self.ca_file) as ws:
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
opcode, data = ws.read()
|
||||||
|
data = data.decode('UTF-8')
|
||||||
|
|
||||||
|
if opcode == OPCODE_PING:
|
||||||
|
ws.write(data=self.data, opcode=OPCODE_PONG)
|
||||||
|
if opcode == OPCODE_TEXT:
|
||||||
|
if data == CORRECT_ASYNC_DATA:
|
||||||
|
self.async_response = True
|
||||||
|
Utility.console_log('Thread {} obtained correct async message'.format(self.name))
|
||||||
|
# Keep sending pong to update the keepalive in the server
|
||||||
|
if (time.time() - self.start_time) > 20:
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
Utility.console_log('Failed to connect to the client and read async data')
|
||||||
|
self.exc = e # type: ignore
|
||||||
|
if self.async_response is not True:
|
||||||
|
self.exc = RuntimeError('Failed to obtain correct async data') # type: ignore
|
||||||
|
|
||||||
|
def join(self, timeout=0): # type:(Optional[float]) -> None
|
||||||
|
threading.Thread.join(self)
|
||||||
|
if self.exc:
|
||||||
|
raise self.exc
|
||||||
|
|
||||||
|
|
||||||
|
def test_multiple_client_keep_alive_and_async_response(ip, port, ca_file): # type: (str, int, str) -> None
|
||||||
|
threads = []
|
||||||
|
for _ in range(3):
|
||||||
|
try:
|
||||||
|
thread = wss_client_thread(ip, port, ca_file)
|
||||||
|
thread.start()
|
||||||
|
threads.append(thread)
|
||||||
|
except OSError:
|
||||||
|
Utility.console_log('Error: unable to start thread')
|
||||||
|
# keep delay of 5 seconds between two connections to avoid handshake timeout
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
|
for t in threads:
|
||||||
|
t.join()
|
||||||
|
|
||||||
|
|
||||||
|
@ttfw_idf.idf_example_test(env_tag='Example_WIFI')
|
||||||
|
def test_examples_protocol_https_wss_server(env, extra_data): # type: (tiny_test_fw.Env.Env, None) -> None # pylint: disable=unused-argument
|
||||||
|
|
||||||
|
# Acquire DUT
|
||||||
|
dut1 = env.get_dut('https_server', 'examples/protocols/https_server/wss_server', dut_class=ttfw_idf.ESP32DUT)
|
||||||
|
|
||||||
|
# Get binary file
|
||||||
|
binary_file = os.path.join(dut1.app.binary_path, 'wss_server.bin')
|
||||||
|
bin_size = os.path.getsize(binary_file)
|
||||||
|
ttfw_idf.log_performance('https_wss_server_bin_size', '{}KB'.format(bin_size // 1024))
|
||||||
|
|
||||||
|
# Upload binary and start testing
|
||||||
|
Utility.console_log('Starting wss_server test app')
|
||||||
|
dut1.start_app()
|
||||||
|
|
||||||
|
# Parse IP address of STA
|
||||||
|
got_port = dut1.expect(re.compile(r'Server listening on port (\d+)'), timeout=60)[0]
|
||||||
|
Utility.console_log('Waiting to connect with AP')
|
||||||
|
got_ip = dut1.expect(re.compile(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)'), timeout=60)[0]
|
||||||
|
|
||||||
|
Utility.console_log('Got IP : ' + got_ip)
|
||||||
|
Utility.console_log('Got Port : ' + got_port)
|
||||||
|
|
||||||
|
ca_file = os.path.join(os.path.dirname(__file__), 'main', 'certs', 'cacert.pem')
|
||||||
|
# Start ws server test
|
||||||
|
with WsClient(got_ip, int(got_port), ca_file) as ws:
|
||||||
|
# Check for echo
|
||||||
|
DATA = 'Espressif'
|
||||||
|
dut1.expect('performing session handshake')
|
||||||
|
client_fd = dut1.expect(re.compile(r'New client connected (\d+)'), timeout=20)[0]
|
||||||
|
ws.write(data=DATA, opcode=OPCODE_TEXT)
|
||||||
|
dut1.expect(re.compile(r'Received packet with message: {}'.format(DATA)))
|
||||||
|
opcode, data = ws.read()
|
||||||
|
data = data.decode('UTF-8')
|
||||||
|
if data != DATA:
|
||||||
|
raise RuntimeError('Failed to receive the correct echo response')
|
||||||
|
Utility.console_log('Correct echo response obtained from the wss server')
|
||||||
|
|
||||||
|
# Test for keepalive
|
||||||
|
Utility.console_log('Testing for keep alive (approx time = 20s)')
|
||||||
|
start_time = time.time()
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
opcode, data = ws.read()
|
||||||
|
if opcode == OPCODE_PING:
|
||||||
|
ws.write(data='Espressif', opcode=OPCODE_PONG)
|
||||||
|
Utility.console_log('Received PING, replying PONG (to update the keepalive)')
|
||||||
|
# Keep sending pong to update the keepalive in the server
|
||||||
|
if (time.time() - start_time) > 20:
|
||||||
|
break
|
||||||
|
except Exception:
|
||||||
|
Utility.console_log('Failed the test for keep alive,\nthe client got abruptly disconnected')
|
||||||
|
raise
|
||||||
|
|
||||||
|
# keepalive timeout is 10 seconds so do not respond for (10 + 1) senconds
|
||||||
|
Utility.console_log('Testing if client is disconnected if it does not respond for 10s i.e. keep_alive timeout (approx time = 11s)')
|
||||||
|
try:
|
||||||
|
dut1.expect('Client not alive, closing fd {}'.format(client_fd), timeout=20)
|
||||||
|
dut1.expect('Client disconnected {}'.format(client_fd))
|
||||||
|
except Exception:
|
||||||
|
Utility.console_log('ENV_ERROR:Failed the test for keep alive,\nthe connection was not closed after timeout')
|
||||||
|
|
||||||
|
time.sleep(11)
|
||||||
|
Utility.console_log('Passed the test for keep alive')
|
||||||
|
|
||||||
|
# Test keep alive and async response for multiple simultaneous client connections
|
||||||
|
Utility.console_log('Testing for multiple simultaneous client connections (approx time = 30s)')
|
||||||
|
test_multiple_client_keep_alive_and_async_response(got_ip, int(got_port), ca_file)
|
||||||
|
Utility.console_log('Passed the test for multiple simultaneous client connections')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_examples_protocol_https_wss_server() # pylint: disable=no-value-for-parameter
|
Reference in New Issue
Block a user