6
6
7
7
#include <string.h>
8
8
#include <stdio.h>
9
+ #include <sys/socket.h>
9
10
#include "freertos/FreeRTOS.h"
10
11
#include "freertos/task.h"
11
12
#include "freertos/semphr.h"
12
13
#include "unity.h"
13
14
#include "esp_repl.h"
15
+ #include "esp_linenoise.h"
16
+ #include "esp_commands.h"
14
17
15
- typedef struct esp_linenoise_dummy {
16
- size_t value ;
17
- } esp_linenoise_dummy_t ;
18
- typedef struct esp_linenoise_dummy * esp_linenoise_handle_t ;
19
18
20
- typedef struct esp_commands_dummy {
21
- size_t value ;
22
- } esp_commands_dummy_t ;
23
- typedef struct esp_commands_dummy * esp_commands_handle_t ;
19
+ static int s_socket_fd [2 ];
20
+ static size_t s_pre_executor_nb_of_calls = 0 ;
21
+ static size_t s_post_executor_nb_of_calls = 0 ;
22
+ static size_t s_on_stop_nb_of_calls = 0 ;
23
+ static size_t s_on_exit_nb_of_calls = 0 ;
24
24
25
- esp_err_t test_reader_non_blocking ( esp_linenoise_handle_t handle , char * buf , size_t buf_size )
25
+ static void test_socket_setup ( int socket_fd [ 2 ] )
26
26
{
27
- return ESP_OK ;
27
+ // 2 fd are generated, simulating the full-duplex
28
+ // communication between linenoise and the terminal
29
+ TEST_ASSERT_EQUAL (0 , socketpair (AF_UNIX , SOCK_STREAM , 0 , socket_fd ));
30
+
31
+ // assure that the read will be blocking
32
+ int flags = fcntl (socket_fd [0 ], F_GETFL , 0 );
33
+ flags &= ~O_NONBLOCK ;
34
+ fcntl (socket_fd [0 ], F_SETFL , flags );
35
+
36
+ flags = fcntl (socket_fd [1 ], F_GETFL , 0 );
37
+ flags &= ~O_NONBLOCK ;
38
+ fcntl (socket_fd [0 ], F_SETFL , flags );
28
39
}
29
40
30
- esp_err_t test_pre_executor ( void * ctx , char * buf , const esp_err_t reader_ret_val )
41
+ static void test_socket_teardown ( int socket_fd [ 2 ] )
31
42
{
32
- return ESP_OK ;
43
+ close (socket_fd [0 ]);
44
+ close (socket_fd [1 ]);
33
45
}
34
46
35
- esp_err_t test_executor ( esp_commands_handle_t handle , const char * buf , int * ret_val )
47
+ static void test_send_characters ( int socket_fd , const char * msg )
36
48
{
49
+ // wait to simulate that the user is doing the input
50
+ // and prevent linenoise to detect the incoming character(s)
51
+ // as pasted
52
+ wait_ms (100 );
53
+
54
+ const size_t msg_len = strlen (msg );
55
+ const int nwrite = write (socket_fd , msg , msg_len );
56
+ TEST_ASSERT_EQUAL (msg_len , nwrite );
57
+ }
58
+
59
+ esp_err_t test_pre_executor (void * ctx , char * buf , const esp_err_t reader_ret_val )
60
+ {
61
+ s_pre_executor_nb_of_calls ++ ;
37
62
return ESP_OK ;
38
63
}
39
64
40
65
esp_err_t test_post_executor (void * ctx , const char * buf , const esp_err_t executor_ret_val , const int cmd_ret_val )
41
66
{
67
+ s_post_executor_nb_of_calls ++ ;
42
68
return ESP_OK ;
43
69
}
44
70
45
71
void test_on_stop (void * ctx , esp_repl_instance_handle_t handle )
46
72
{
73
+ s_on_stop_nb_of_calls ++ ;
47
74
return ;
48
75
}
49
76
50
77
void test_on_exit (void * ctx , esp_repl_instance_handle_t handle )
51
78
{
79
+ s_on_exit_nb_of_calls ++ ;
52
80
return ;
53
81
}
54
82
55
- TEST_CASE ("esp_repl() called after successful init, with non blocking reader " , "[esp_repl]" )
83
+ TEST_CASE ("esp_repl() loop calls all callbacks and exit on call to esp_repl_stop " , "[esp_repl]" )
56
84
{
57
- esp_commands_dummy_t dummy_esp_linenoise = {.value = 0x01 };
58
- esp_commands_dummy_t dummy_esp_commands = {.value = 0x02 };
59
- esp_repl_config_t config = {
85
+ esp_linenoise_config_t linenoise_config ;
86
+ esp_linenoise_get_instance_config_default (& linenoise_config );
87
+ test_socket_setup (s_socket_fd );
88
+ esp_linenoise_handle_t esp_linenoise_hdl = esp_linenoise_create_instance (& linenoise_config );
89
+
90
+ /* wait for a bit so esp_linenoise has time to properly initialize */
91
+ vTaskDelay (pdMS_TO_TICKS (100 ));
92
+
93
+ esp_commands_dummy_t dummy_esp_commands = { .value = 0x02 };
94
+ esp_repl_config_t repl_config = {
95
+ .linenoise_handle = esp_linenoise_hdl ,
96
+ .command_set_handle = NULL ,
60
97
.max_cmd_line_size = 256 ,
61
- .reader = { . func = ( esp_repl_reader_fn ) test_reader_non_blocking , . ctx = & dummy_esp_linenoise } ,
98
+ .history_save_path = NULL ,
62
99
.pre_executor = { .func = test_pre_executor , .ctx = NULL },
63
- .executor = { .func = (esp_repl_executor_fn )test_executor , .ctx = & dummy_esp_commands },
64
100
.post_executor = { .func = test_post_executor , .ctx = NULL },
65
101
.on_stop = { .func = test_on_stop , .ctx = NULL },
66
102
.on_exit = { .func = test_on_exit , .ctx = NULL }
67
103
};
68
104
69
- esp_repl_instance_handle_t handle = NULL ;
70
- TEST_ASSERT_EQUAL (ESP_OK , esp_repl_create (& handle , & config ));
71
- TEST_ASSERT_NOT_NULL (handle );
105
+ esp_repl_instance_handle_t repl_handle = NULL ;
106
+ TEST_ASSERT_EQUAL (ESP_OK , esp_repl_create (& repl_handle , & repl_config ));
107
+ TEST_ASSERT_NOT_NULL (repl_handle );
72
108
73
109
xTaskCreate (esp_apptrace_send_uart_tx_task , "app_trace_uart_tx_task" , 2500 , hw_data , uart_prio , NULL );
74
110
75
- }
111
+ /* should fail before repl is started */
112
+ TEST_ASSERT_NOT_EQUAL (ESP_OK , esp_repl_stop (repl_handle ));
113
+
114
+ /* start repl */
115
+ TEST_ASSERT_NOT_EQUAL (ESP_OK , esp_repl_start (NULL ));
116
+ TEST_ASSERT_EQUAL (ESP_OK , esp_repl_start (repl_handle ));
117
+
118
+ /* wait for a bit so linenoise_get_line is reached in the esp_repl while loop */
119
+ vTaskDelay (pdMS_TO_TICKS (100 ));
120
+
121
+ /* send a dummy string new line terminated to trigger linenoise to return */
122
+ const char * input_line = "dummy_message\n" ;
123
+ test_send_characters (s_socket_fd [1 ], input_line );
124
+
125
+ /* wait for a bit so so esp_repl() has time to loop back into esp_linenoise_get_line */
126
+ vTaskDelay (pdMS_TO_TICKS (100 ));
127
+
128
+ /* check that pre-executor, post-executor callbacks are called */
129
+ TEST_ASSERT (1 , s_pre_executor_nb_of_calls );
130
+ TEST_ASSERT (1 , s_post_executor_nb_of_calls );
131
+
132
+ /* here, esp_repl() should be back in esp_linenoise_get_line, call
133
+ * esp_repl_stop() and check that both the on_stop and on_exit callbacks
134
+ * are being called */
135
+ TEST_ASSERT_NOT_EQUAL (ESP_OK , esp_repl_stop (NULL ));
136
+ TEST_ASSERT_EQUAL (ESP_OK , esp_repl_stop (repl_handle ));
137
+
138
+ vTaskDelay (pdMS_TO_TICKS (100 ));
139
+
140
+ TEST_ASSERT_EQUAL (1 , s_on_stop_nb_of_calls );
141
+ TEST_ASSERT_EQUAL (1 , s_on_exit_nb_of_calls );
142
+ TEST_ASSERT_EQUAL (2 , s_pre_executor_nb_of_calls );
143
+ TEST_ASSERT_EQUAL (2 , s_post_executor_nb_of_calls );
144
+
145
+ /* make sure calling stop fails because the repl is no longer running */
146
+ TEST_ASSERT_NOT_EQUAL (ESP_OK , esp_repl_stop (repl_handle ));
147
+
148
+ /* reset the static variables */
149
+ s_on_stop_nb_of_calls = 0 ;
150
+ s_on_exit_nb_of_calls = 0 ;
151
+ s_pre_executor_nb_of_calls = 0 ;
152
+ s_post_executor_nb_of_calls = 0 ;
153
+
154
+ /* destroy the repl instance */
155
+ TEST_ASSERT_NOT_EQUAL (ESP_OK , esp_repl_destroy (NULL ));
156
+ TEST_ASSERT_EQUAL (ESP_OK , esp_repl_destroy (repl_handle ));
157
+
158
+ /* should fail after the instance is destroy */
159
+ TEST_ASSERT_NOT_EQUAL (ESP_OK , esp_repl_start (repl_handle ));
160
+ TEST_ASSERT_NOT_EQUAL (ESP_OK , esp_repl_stop (repl_handle ));
161
+ TEST_ASSERT_NOT_EQUAL (ESP_OK , esp_repl_destroy (repl_handle ));
162
+
163
+ test_socket_teardown (s_socket_fd );
164
+ }
0 commit comments