Skip to content

Commit 61a8a6b

Browse files
authored
emulation on host: fix nasty delay (#5840)
emulation with socket: fix nasty delay properly check all return values (read() returning 0 indicates closed peer) ClientContext::state() triggers read() to check for closed peer uart emulation on tty: add cmdline -b debug option to disable raw tty hide annoying MOCK messages, add cmdline -v option to show them uart emulation on tty: check more return values emulation on host: tcp/udp port shifting: new cmdline -s(port Shift) option
1 parent 22eeb94 commit 61a8a6b

13 files changed

+169
-82
lines changed

tests/host/common/ArduinoMain.cpp

+67-15
Original file line numberDiff line numberDiff line change
@@ -39,30 +39,55 @@
3939
#include <stdarg.h>
4040
#include <stdio.h>
4141

42+
#define MOCK_PORT_SHIFTER 9000
43+
4244
bool user_exit = false;
4345
const char* host_interface = nullptr;
4446
size_t spiffs_kb = 1024;
4547
bool ignore_sigint = false;
4648
bool restore_tty = false;
49+
bool mockdebug = false;
50+
int mock_port_shifter = MOCK_PORT_SHIFTER;
4751

4852
#define STDIN STDIN_FILENO
4953

5054
static struct termios initial_settings;
5155

56+
int mockverbose (const char* fmt, ...)
57+
{
58+
va_list ap;
59+
va_start(ap, fmt);
60+
if (mockdebug)
61+
return fprintf(stderr, MOCK) + vfprintf(stderr, fmt, ap);
62+
return 0;
63+
}
64+
5265
static int mock_start_uart(void)
5366
{
5467
struct termios settings;
5568

56-
if (!isatty(STDIN)) return 0;
57-
if (tcgetattr(STDIN, &initial_settings) < 0) return -1;
69+
if (!isatty(STDIN))
70+
{
71+
perror("setting tty in raw mode: isatty(STDIN)");
72+
return -1;
73+
}
74+
if (tcgetattr(STDIN, &initial_settings) < 0)
75+
{
76+
perror("setting tty in raw mode: tcgetattr(STDIN)");
77+
return -1;
78+
}
5879
settings = initial_settings;
5980
settings.c_lflag &= ~(ignore_sigint ? ISIG : 0);
6081
settings.c_lflag &= ~(ECHO | ICANON);
6182
settings.c_iflag &= ~(ICRNL | INLCR | ISTRIP | IXON);
6283
settings.c_oflag |= (ONLCR);
6384
settings.c_cc[VMIN] = 0;
6485
settings.c_cc[VTIME] = 0;
65-
if (tcsetattr(STDIN, TCSANOW, &settings) < 0) return -2;
86+
if (tcsetattr(STDIN, TCSANOW, &settings) < 0)
87+
{
88+
perror("setting tty in raw mode: tcsetattr(STDIN)");
89+
return -1;
90+
}
6691
restore_tty = true;
6792
return 0;
6893
}
@@ -71,11 +96,14 @@ static int mock_stop_uart(void)
7196
{
7297
if (!restore_tty) return 0;
7398
if (!isatty(STDIN)) {
74-
perror("isatty(STDIN)");
75-
//system("stty sane"); <- same error message "Inappropriate ioctl for device"
76-
return 0;
99+
perror("restoring tty: isatty(STDIN)");
100+
return -1;
101+
}
102+
if (tcsetattr(STDIN, TCSANOW, &initial_settings) < 0)
103+
{
104+
perror("restoring tty: tcsetattr(STDIN)");
105+
return -1;
77106
}
78-
if (tcsetattr(STDIN, TCSANOW, &initial_settings) < 0) return -1;
79107
printf("\e[?25h"); // show cursor
80108
return (0);
81109
}
@@ -94,11 +122,14 @@ void help (const char* argv0, int exitcode)
94122
" -h\n"
95123
" -i <interface> - use this interface for IP address\n"
96124
" -l - bind tcp/udp servers to interface only (not 0.0.0.0)\n"
125+
" -s - port shifter (default: %d, when root: 0)\n"
97126
" -c - ignore CTRL-C (send it via Serial)\n"
98127
" -f - no throttle (possibly 100%%CPU)\n"
128+
" -b - blocking tty/mocked-uart (default: not blocking tty)\n"
99129
" -S - spiffs size in KBytes (default: %zd)\n"
130+
" -v - mock verbose\n"
100131
" (negative value will force mismatched size)\n"
101-
, argv0, spiffs_kb);
132+
, argv0, MOCK_PORT_SHIFTER, spiffs_kb);
102133
exit(exitcode);
103134
}
104135

@@ -108,8 +139,11 @@ static struct option options[] =
108139
{ "fast", no_argument, NULL, 'f' },
109140
{ "local", no_argument, NULL, 'l' },
110141
{ "sigint", no_argument, NULL, 'c' },
142+
{ "blockinguart", no_argument, NULL, 'b' },
143+
{ "verbose", no_argument, NULL, 'v' },
111144
{ "interface", required_argument, NULL, 'i' },
112145
{ "spiffskb", required_argument, NULL, 'S' },
146+
{ "portshifter", required_argument, NULL, 's' },
113147
};
114148

115149
void cleanup ()
@@ -133,13 +167,18 @@ void control_c (int sig)
133167

134168
int main (int argc, char* const argv [])
135169
{
136-
signal(SIGINT, control_c);
137-
138170
bool fast = false;
171+
bool blocking_uart = false;
172+
173+
signal(SIGINT, control_c);
174+
if (geteuid() == 0)
175+
mock_port_shifter = 0;
176+
else
177+
mock_port_shifter = MOCK_PORT_SHIFTER;
139178

140179
for (;;)
141180
{
142-
int n = getopt_long(argc, argv, "hlcfi:S:", options, NULL);
181+
int n = getopt_long(argc, argv, "hlcfbvi:S:s:", options, NULL);
143182
if (n < 0)
144183
break;
145184
switch (n)
@@ -153,6 +192,9 @@ int main (int argc, char* const argv [])
153192
case 'l':
154193
global_ipv4_netfmt = NO_GLOBAL_BINDING;
155194
break;
195+
case 's':
196+
mock_port_shifter = atoi(optarg);
197+
break;
156198
case 'c':
157199
ignore_sigint = true;
158200
break;
@@ -162,12 +204,19 @@ int main (int argc, char* const argv [])
162204
case 'S':
163205
spiffs_kb = atoi(optarg);
164206
break;
207+
case 'b':
208+
blocking_uart = true;
209+
break;
210+
case 'v':
211+
mockdebug = true;
212+
break;
165213
default:
166-
fprintf(stderr, MOCK "bad option '%c'\n", n);
167-
exit(EXIT_FAILURE);
214+
help(argv[0], EXIT_FAILURE);
168215
}
169216
}
170217

218+
mockverbose("server port shifter: %d\n", mock_port_shifter);
219+
171220
if (spiffs_kb)
172221
{
173222
String name = argv[0];
@@ -180,8 +229,11 @@ int main (int argc, char* const argv [])
180229
// setup global global_ipv4_netfmt
181230
wifi_get_ip_info(0, nullptr);
182231

183-
// set stdin to non blocking mode
184-
mock_start_uart();
232+
if (!blocking_uart)
233+
{
234+
// set stdin to non blocking mode
235+
mock_start_uart();
236+
}
185237

186238
// install exit handler in case Esp.restart() is called
187239
atexit(cleanup);

tests/host/common/ArduinoMainUdp.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ void check_incoming_udp ()
5858
p.events = POLLIN;
5959
if (poll(&p, 1, 0) && p.revents == POLLIN)
6060
{
61-
fprintf(stderr, MOCK "UDP poll(%d) -> cb\r", p.fd);
61+
mockverbose("UDP poll(%d) -> cb\r", p.fd);
6262
udp.second->mock_cb();
6363
}
6464
}

tests/host/common/ClientContextSocket.cpp

+13-5
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ int mockSockSetup (int sock)
4343
{
4444
if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
4545
{
46-
fprintf(stderr, MOCK "socket fcntl(O_NONBLOCK): %s\n", strerror(errno));
46+
perror("socket fcntl(O_NONBLOCK)");
4747
close(sock);
4848
return -1;
4949
}
@@ -52,7 +52,8 @@ int mockSockSetup (int sock)
5252
int i = 1;
5353
if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &i, sizeof i) == -1)
5454
{
55-
fprintf(stderr, MOCK "sockopt( SO_NOSIGPIPE)(macOS): %s\n", strerror(errno));
55+
perror("sockopt(SO_NOSIGPIPE)(macOS)");
56+
close(sock);
5657
return -1;
5758
}
5859
#endif
@@ -84,6 +85,13 @@ ssize_t mockFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize)
8485
{
8586
size_t maxread = CCBUFSIZE - ccinbufsize;
8687
ssize_t ret = ::read(sock, ccinbuf + ccinbufsize, maxread);
88+
89+
if (ret == 0)
90+
{
91+
// connection closed
92+
return -1;
93+
}
94+
8795
if (ret == -1)
8896
{
8997
if (errno != EAGAIN)
@@ -100,7 +108,7 @@ ssize_t mockFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize)
100108
ssize_t mockPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
101109
{
102110
if (usersize > CCBUFSIZE)
103-
fprintf(stderr, MOCK "CCBUFSIZE(%d) should be increased by %zd bytes (-> %zd)\n", CCBUFSIZE, usersize - CCBUFSIZE, usersize);
111+
mockverbose("CCBUFSIZE(%d) should be increased by %zd bytes (-> %zd)\n", CCBUFSIZE, usersize - CCBUFSIZE, usersize);
104112

105113
struct pollfd p;
106114
size_t retsize = 0;
@@ -163,12 +171,12 @@ ssize_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms)
163171
#endif
164172
if (ret == -1)
165173
{
166-
fprintf(stderr, MOCK "ClientContext::read: write(%d): %s\n", sock, strerror(errno));
174+
fprintf(stderr, MOCK "ClientContext::write(%d): %s\n", sock, strerror(errno));
167175
return -1;
168176
}
169177
if (ret != (int)size)
170178
{
171-
fprintf(stderr, MOCK "ClientContext::write: short write (%d < %zd) (TODO)\n", ret, size);
179+
fprintf(stderr, MOCK "ClientContext::write: short write (%d < %zd) (FIXME poll loop TODO)\n", ret, size);
172180
exit(EXIT_FAILURE);
173181
}
174182
}

tests/host/common/HostWiring.cpp

+11-15
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@
3131

3232
#include <Arduino.h>
3333

34+
#ifdef DEBUG_ESP_CORE
35+
#define VERBOSE(x...) fprintf(stderr, MOCK x)
36+
#else
37+
#define VERBOSE(x...) mockverbose(x)
38+
#endif
39+
3440
void pinMode (uint8_t pin, uint8_t mode)
3541
{
3642
#define xxx(mode) case mode: m=STRHELPER(mode); break
@@ -46,23 +52,17 @@ void pinMode (uint8_t pin, uint8_t mode)
4652
case WAKEUP_PULLDOWN: m="WAKEUP_PULLDOWN"; break;
4753
default: m="(special)";
4854
}
49-
#ifdef DEBUG_ESP_CORE
50-
fprintf(stderr, MOCK "gpio%d: mode='%s'\n", pin, m);
51-
#endif
55+
VERBOSE("gpio%d: mode='%s'\n", pin, m);
5256
}
5357

5458
void digitalWrite(uint8_t pin, uint8_t val)
5559
{
56-
#ifdef DEBUG_ESP_CORE
57-
fprintf(stderr, MOCK "digitalWrite(pin=%d val=%d)\n", pin, val);
58-
#endif
60+
VERBOSE("digitalWrite(pin=%d val=%d)\n", pin, val);
5961
}
6062

6163
void analogWrite(uint8_t pin, int val)
6264
{
63-
#ifdef DEBUG_ESP_CORE
64-
fprintf(stderr, MOCK "analogWrite(pin=%d, val=%d\n", pin, val);
65-
#endif
65+
VERBOSE("analogWrite(pin=%d, val=%d\n", pin, val);
6666
}
6767

6868
int analogRead(uint8_t pin)
@@ -73,16 +73,12 @@ int analogRead(uint8_t pin)
7373

7474
void analogWriteRange(uint32_t range)
7575
{
76-
#ifdef DEBUG_ESP_CORE
77-
fprintf(stderr, MOCK "analogWriteRange(range=%d)\n", range);
78-
#endif
76+
VERBOSE("analogWriteRange(range=%d)\n", range);
7977
}
8078

8179
int digitalRead(uint8_t pin)
8280
{
83-
#ifdef DEBUG_ESP_CORE
84-
fprintf(stderr, MOCK "digitalRead(%d)\n", pin);
85-
#endif
81+
VERBOSE("digitalRead(%d)\n", pin);
8682

8783
// pin 0 is most likely a low active input
8884
return pin ? 0 : 1;

tests/host/common/MockEsp.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ EspClass ESP;
8181

8282
void EspClass::restart ()
8383
{
84-
fprintf(stderr, MOCK "Esp.restart(): exiting\n");
84+
mockverbose("Esp.restart(): exiting\n");
8585
exit(EXIT_SUCCESS);
8686
}
8787

tests/host/common/MockTools.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ extern "C" void configTime(long timezone, int daylightOffset_sec,
5959
(void)server2;
6060
(void)server3;
6161

62-
fprintf(stderr, MOCK "configTime: TODO (tz=%ldH offset=%dS) (time will be host's)\n", timezone, daylightOffset_sec);
62+
mockverbose("configTime: TODO (tz=%ldH offset=%dS) (time will be host's)\n", timezone, daylightOffset_sec);
6363
}
6464

6565
void stack_thunk_add_ref() { }

tests/host/common/MockWiFiServer.cpp

-12
Original file line numberDiff line numberDiff line change
@@ -47,23 +47,11 @@ extern "C" const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY);
4747
WiFiServer::WiFiServer (const IPAddress& addr, uint16_t port)
4848
{
4949
(void)addr;
50-
if (port < 1024)
51-
{
52-
int newport = port + 9000;
53-
fprintf(stderr, MOCK "WiFiServer port: %d -> %d\n", port, newport);
54-
port = newport;
55-
}
5650
_port = port;
5751
}
5852

5953
WiFiServer::WiFiServer (uint16_t port)
6054
{
61-
if (port < 1024)
62-
{
63-
int newport = port + 9000;
64-
fprintf(stderr, MOCK "WiFiServer port: %d -> %d\n", port, newport);
65-
port = newport;
66-
}
6755
_port = port;
6856
}
6957

tests/host/common/MockWiFiServerSocket.cpp

+12-1
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,18 @@ void WiFiServer::begin (uint16_t port)
6767
void WiFiServer::begin ()
6868
{
6969
int sock;
70+
int mockport;
7071
struct sockaddr_in server;
7172

73+
mockport = _port;
74+
if (mockport < 1024 && mock_port_shifter)
75+
{
76+
mockport += mock_port_shifter;
77+
fprintf(stderr, MOCK "=====> WiFiServer port: %d shifted to %d (use option -s) <=====\n", _port, mockport);
78+
}
79+
else
80+
fprintf(stderr, MOCK "=====> WiFiServer port: %d <=====\n", mockport);
81+
7282
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
7383
{
7484
perror(MOCK "socket()");
@@ -83,7 +93,7 @@ void WiFiServer::begin ()
8393
}
8494

8595
server.sin_family = AF_INET;
86-
server.sin_port = htons(_port);
96+
server.sin_port = htons(mockport);
8797
server.sin_addr.s_addr = htonl(INADDR_ANY);
8898
if (bind(sock, (struct sockaddr*)&server, sizeof(server)) == -1)
8999
{
@@ -118,6 +128,7 @@ size_t WiFiServer::write (uint8_t c)
118128
size_t WiFiServer::write (const uint8_t *buf, size_t size)
119129
{
120130
fprintf(stderr, MOCK "todo: WiFiServer::write(%p, %zd)\n", buf, size);
131+
exit(EXIT_FAILURE);
121132
return 0;
122133
}
123134

0 commit comments

Comments
 (0)