Skip to content

Commit 24048d8

Browse files
committed
feat(usb_serial_tag_vfs): Add test for read exit conditions
Add a test to make sure the VFS read does not return on reception of the \n character
1 parent a327069 commit 24048d8

File tree

5 files changed

+128
-8
lines changed

5 files changed

+128
-8
lines changed

components/esp_driver_usb_serial_jtag/src/usb_serial_jtag_vfs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,11 @@ static void usb_serial_jtag_return_char(int fd, int c)
226226

227227
static ssize_t usb_serial_jtag_read(int fd, void* data, size_t size)
228228
{
229+
assert(fd == USJ_LOCAL_FD);
229230
char *data_c = (char *) data;
230231
size_t received = 0;
231232
_lock_acquire_recursive(&s_ctx.read_lock);
233+
232234
while (received < size) {
233235
int c = usb_serial_jtag_read_char(fd);
234236
if (c == '\r') {

components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag_vfs/main/test_vfs_usb_serial_jtag.c

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -23,11 +23,6 @@
2323
#include "test_utils.h"
2424
#include "sdkconfig.h"
2525

26-
struct task_arg_t {
27-
FILE* stream;
28-
SemaphoreHandle_t done;
29-
};
30-
3126
static int read_bytes_with_select(FILE *stream, void *buf, size_t buf_len, struct timeval tv)
3227
{
3328

@@ -74,7 +69,7 @@ static int read_bytes_with_select(FILE *stream, void *buf, size_t buf_len, struc
7469
* write calls. At the end of the test, the variable is check to make sure the select returned
7570
* for each of the write calls.
7671
*/
77-
TEST_CASE("test select read, write and timeout", "[usb_serial_jtag]")
72+
TEST_CASE("test select read, write and timeout", "[usb_serial_jtag vfs]")
7873
{
7974
struct timeval tv;
8075
tv.tv_sec = 1;
@@ -128,3 +123,55 @@ TEST_CASE("test select read, write and timeout", "[usb_serial_jtag]")
128123
usb_serial_jtag_vfs_use_nonblocking();
129124
usb_serial_jtag_driver_uninstall();
130125
}
126+
127+
TEST_CASE("read with usj driver (non-blocking)", "[usb serial jtag vfs]")
128+
{
129+
// Send a string with length less than the read requested length
130+
const char in_buffer[] = "!(@*#&(!*@&#((SDasdkjhad\nce"; // read should not early return on \n
131+
const size_t in_buffer_len = sizeof(in_buffer);
132+
133+
const size_t out_buffer_len = in_buffer_len - 1; // don't compare the null character at the end of in_buffer string
134+
char out_buffer[out_buffer_len] = {};
135+
136+
// flush_stdin_stdout();
137+
138+
usb_serial_jtag_driver_config_t usj_config = USB_SERIAL_JTAG_DRIVER_CONFIG_DEFAULT();
139+
ESP_ERROR_CHECK(usb_serial_jtag_driver_install(&usj_config));
140+
usb_serial_jtag_vfs_use_driver();
141+
142+
usb_serial_jtag_vfs_set_rx_line_endings(ESP_LINE_ENDINGS_LF);
143+
usb_serial_jtag_vfs_set_tx_line_endings(ESP_LINE_ENDINGS_LF);
144+
145+
int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
146+
fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
147+
148+
// trigger the test environment to send the test message
149+
char ready_msg[] = "ready to receive\n";
150+
write(fileno(stdout), ready_msg, sizeof(ready_msg));
151+
152+
// wait for the string to be sent and buffered
153+
vTaskDelay(pdMS_TO_TICKS(500));
154+
155+
char *out_buffer_ptr = out_buffer;
156+
size_t bytes_read = 0;
157+
do {
158+
int nread = read(STDIN_FILENO, out_buffer_ptr, out_buffer_len);
159+
printf("%d\n", nread);
160+
if (nread > 0) {
161+
out_buffer_ptr += nread;
162+
bytes_read += nread;
163+
}
164+
} while (bytes_read < in_buffer_len);
165+
166+
// string compare
167+
for (size_t i = 0; i < out_buffer_len; i++) {
168+
TEST_ASSERT_EQUAL(in_buffer[i], out_buffer[i]);
169+
}
170+
171+
usb_serial_jtag_vfs_use_nonblocking();
172+
fcntl(STDIN_FILENO, F_SETFL, flags);
173+
usb_serial_jtag_vfs_set_rx_line_endings(ESP_LINE_ENDINGS_CRLF);
174+
usb_serial_jtag_vfs_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF);
175+
ESP_ERROR_CHECK(usb_serial_jtag_driver_uninstall());
176+
vTaskDelay(2); // wait for tasks to exit
177+
}

components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag_vfs/pytest_usb_serial_jtag_vfs.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,28 @@
1515
)
1616
@pytest.mark.parametrize('test_message', ['test123456789!@#%^&*'])
1717
@idf_parametrize('target', ['esp32s3', 'esp32c3', 'esp32c6', 'esp32h2'], indirect=['target'])
18-
def test_usj_vfs_release(dut: Dut, test_message: list) -> None:
18+
def test_usj_vfs_select(dut: Dut, test_message: list) -> None:
1919
dut.expect_exact('Press ENTER to see the list of tests')
2020
dut.write('"test select read, write and timeout"')
2121
dut.expect_exact('select timed out', timeout=2)
2222
dut.write(test_message)
2323
dut.expect_exact(test_message, timeout=2)
2424
dut.expect(r'\d{1} Tests 0 Failures 0 Ignored', timeout=10)
25+
26+
27+
@pytest.mark.usb_serial_jtag
28+
@pytest.mark.parametrize(
29+
'port, config',
30+
[
31+
pytest.param('/dev/ttyACM1', 'release'),
32+
],
33+
indirect=True,
34+
)
35+
@pytest.mark.parametrize('test_message', ['!(@*#&(!*@&#((SDasdkjhad\nce'])
36+
@idf_parametrize('target', ['esp32s3', 'esp32c3', 'esp32c6', 'esp32h2'], indirect=['target'])
37+
def test_usj_vfs_read(dut: Dut, test_message: list) -> None:
38+
dut.expect_exact('Press ENTER to see the list of tests')
39+
dut.write('"read with usj driver (non-blocking)"')
40+
dut.expect_exact('ready to receive', timeout=2)
41+
dut.write(test_message)
42+
dut.expect(r'\d{1} Tests 0 Failures 0 Ignored', timeout=10)

components/esp_vfs_console/test_apps/usb_cdc_vfs/main/test_app_main.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,56 @@ static void test_usb_cdc_read_non_blocking(void)
175175
TEST_ASSERT(errno != EWOULDBLOCK);
176176
}
177177

178+
static void test_usb_cdc_read_no_exit_on_newline_reception(void)
179+
{
180+
test_setup(__func__, sizeof(__func__));
181+
182+
// Send a string with length less than the read requested length
183+
const char in_buffer[] = "!(@*#&(!*@&#((SDasdkjhad\nce"; // read should not early return on \n
184+
const size_t in_buffer_len = sizeof(in_buffer);
185+
186+
const size_t out_buffer_len = in_buffer_len - 1; // don't compare the null character at the end of in_buffer string
187+
char out_buffer[out_buffer_len] = {};
188+
189+
ESP_ERROR_CHECK(esp_vfs_dev_cdcacm_register());
190+
191+
esp_vfs_dev_cdcacm_set_rx_line_endings(ESP_LINE_ENDINGS_LF);
192+
esp_vfs_dev_cdcacm_set_tx_line_endings(ESP_LINE_ENDINGS_LF);
193+
194+
int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
195+
fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
196+
197+
// trigger the test environment to send the test message
198+
char ready_msg[] = "ready to receive\n";
199+
write(fileno(stdout), ready_msg, sizeof(ready_msg));
200+
201+
// wait for the string to be sent and buffered
202+
vTaskDelay(pdMS_TO_TICKS(500));
203+
204+
char *out_buffer_ptr = out_buffer;
205+
size_t bytes_read = 0;
206+
do {
207+
int nread = read(STDIN_FILENO, out_buffer_ptr, out_buffer_len);
208+
if (nread > 0) {
209+
out_buffer_ptr += nread;
210+
bytes_read += nread;
211+
}
212+
} while (bytes_read < in_buffer_len);
213+
214+
// string compare
215+
for (size_t i = 0; i < out_buffer_len; i++) {
216+
TEST_ASSERT_EQUAL(in_buffer[i], out_buffer[i]);
217+
}
218+
219+
fcntl(STDIN_FILENO, F_SETFL, flags);
220+
esp_vfs_dev_cdcacm_set_rx_line_endings(ESP_LINE_ENDINGS_CRLF);
221+
esp_vfs_dev_cdcacm_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF);
222+
vTaskDelay(2); // wait for tasks to exit
223+
}
224+
178225
void app_main(void)
179226
{
180227
test_usb_cdc_select();
181228
test_usb_cdc_read_non_blocking();
229+
test_usb_cdc_read_no_exit_on_newline_reception();
182230
}

components/esp_vfs_console/test_apps/usb_cdc_vfs/pytest_usb_cdc_vfs.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,8 @@ def test_usb_cdc_vfs_default(dut: Dut, test_message: str) -> None:
2626
dut.expect_exact('test_usb_cdc_read_non_blocking', timeout=2)
2727
dut.expect_exact('send_bytes', timeout=2)
2828
dut.write('abcdefgh')
29+
30+
# test run: test_usb_cdc_read_no_exit_on_newline_reception
31+
dut.expect_exact('test_usb_cdc_read_no_exit_on_newline_reception', timeout=2)
32+
dut.expect_exact('ready to receive', timeout=2)
33+
dut.write('!(@*#&(!*@&#((SDasdkjhad\nce')

0 commit comments

Comments
 (0)