Skip to content

emulation on host: fix nasty delay #5840

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Mar 5, 2019
82 changes: 67 additions & 15 deletions tests/host/common/ArduinoMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,30 +39,55 @@
#include <stdarg.h>
#include <stdio.h>

#define MOCK_PORT_SHIFTER 9000

bool user_exit = false;
const char* host_interface = nullptr;
size_t spiffs_kb = 1024;
bool ignore_sigint = false;
bool restore_tty = false;
bool mockdebug = false;
int mock_port_shifter = MOCK_PORT_SHIFTER;

#define STDIN STDIN_FILENO

static struct termios initial_settings;

int mockverbose (const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (mockdebug)
return fprintf(stderr, MOCK) + vfprintf(stderr, fmt, ap);
return 0;
}

static int mock_start_uart(void)
{
struct termios settings;

if (!isatty(STDIN)) return 0;
if (tcgetattr(STDIN, &initial_settings) < 0) return -1;
if (!isatty(STDIN))
{
perror("setting tty in raw mode: isatty(STDIN)");
return -1;
}
if (tcgetattr(STDIN, &initial_settings) < 0)
{
perror("setting tty in raw mode: tcgetattr(STDIN)");
return -1;
}
settings = initial_settings;
settings.c_lflag &= ~(ignore_sigint ? ISIG : 0);
settings.c_lflag &= ~(ECHO | ICANON);
settings.c_iflag &= ~(ICRNL | INLCR | ISTRIP | IXON);
settings.c_oflag |= (ONLCR);
settings.c_cc[VMIN] = 0;
settings.c_cc[VTIME] = 0;
if (tcsetattr(STDIN, TCSANOW, &settings) < 0) return -2;
if (tcsetattr(STDIN, TCSANOW, &settings) < 0)
{
perror("setting tty in raw mode: tcsetattr(STDIN)");
return -1;
}
restore_tty = true;
return 0;
}
Expand All @@ -71,11 +96,14 @@ static int mock_stop_uart(void)
{
if (!restore_tty) return 0;
if (!isatty(STDIN)) {
perror("isatty(STDIN)");
//system("stty sane"); <- same error message "Inappropriate ioctl for device"
return 0;
perror("restoring tty: isatty(STDIN)");
return -1;
}
if (tcsetattr(STDIN, TCSANOW, &initial_settings) < 0)
{
perror("restoring tty: tcsetattr(STDIN)");
return -1;
}
if (tcsetattr(STDIN, TCSANOW, &initial_settings) < 0) return -1;
printf("\e[?25h"); // show cursor
return (0);
}
Expand All @@ -94,11 +122,14 @@ void help (const char* argv0, int exitcode)
" -h\n"
" -i <interface> - use this interface for IP address\n"
" -l - bind tcp/udp servers to interface only (not 0.0.0.0)\n"
" -s - port shifter (default: %d, when root: 0)\n"
" -c - ignore CTRL-C (send it via Serial)\n"
" -f - no throttle (possibly 100%%CPU)\n"
" -b - blocking tty/mocked-uart (default: not blocking tty)\n"
" -S - spiffs size in KBytes (default: %zd)\n"
" -v - mock verbose\n"
" (negative value will force mismatched size)\n"
, argv0, spiffs_kb);
, argv0, MOCK_PORT_SHIFTER, spiffs_kb);
exit(exitcode);
}

Expand All @@ -108,8 +139,11 @@ static struct option options[] =
{ "fast", no_argument, NULL, 'f' },
{ "local", no_argument, NULL, 'l' },
{ "sigint", no_argument, NULL, 'c' },
{ "blockinguart", no_argument, NULL, 'b' },
{ "verbose", no_argument, NULL, 'v' },
{ "interface", required_argument, NULL, 'i' },
{ "spiffskb", required_argument, NULL, 'S' },
{ "portshifter", required_argument, NULL, 's' },
};

void cleanup ()
Expand All @@ -133,13 +167,18 @@ void control_c (int sig)

int main (int argc, char* const argv [])
{
signal(SIGINT, control_c);

bool fast = false;
bool blocking_uart = false;

signal(SIGINT, control_c);
if (geteuid() == 0)
mock_port_shifter = 0;
else
mock_port_shifter = MOCK_PORT_SHIFTER;

for (;;)
{
int n = getopt_long(argc, argv, "hlcfi:S:", options, NULL);
int n = getopt_long(argc, argv, "hlcfbvi:S:s:", options, NULL);
if (n < 0)
break;
switch (n)
Expand All @@ -153,6 +192,9 @@ int main (int argc, char* const argv [])
case 'l':
global_ipv4_netfmt = NO_GLOBAL_BINDING;
break;
case 's':
mock_port_shifter = atoi(optarg);
break;
case 'c':
ignore_sigint = true;
break;
Expand All @@ -162,12 +204,19 @@ int main (int argc, char* const argv [])
case 'S':
spiffs_kb = atoi(optarg);
break;
case 'b':
blocking_uart = true;
break;
case 'v':
mockdebug = true;
break;
default:
fprintf(stderr, MOCK "bad option '%c'\n", n);
exit(EXIT_FAILURE);
help(argv[0], EXIT_FAILURE);
}
}

mockverbose("server port shifter: %d\n", mock_port_shifter);

if (spiffs_kb)
{
String name = argv[0];
Expand All @@ -180,8 +229,11 @@ int main (int argc, char* const argv [])
// setup global global_ipv4_netfmt
wifi_get_ip_info(0, nullptr);

// set stdin to non blocking mode
mock_start_uart();
if (!blocking_uart)
{
// set stdin to non blocking mode
mock_start_uart();
}

// install exit handler in case Esp.restart() is called
atexit(cleanup);
Expand Down
2 changes: 1 addition & 1 deletion tests/host/common/ArduinoMainUdp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ void check_incoming_udp ()
p.events = POLLIN;
if (poll(&p, 1, 0) && p.revents == POLLIN)
{
fprintf(stderr, MOCK "UDP poll(%d) -> cb\r", p.fd);
mockverbose("UDP poll(%d) -> cb\r", p.fd);
udp.second->mock_cb();
}
}
Expand Down
18 changes: 13 additions & 5 deletions tests/host/common/ClientContextSocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ int mockSockSetup (int sock)
{
if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
{
fprintf(stderr, MOCK "socket fcntl(O_NONBLOCK): %s\n", strerror(errno));
perror("socket fcntl(O_NONBLOCK)");
close(sock);
return -1;
}
Expand All @@ -52,7 +52,8 @@ int mockSockSetup (int sock)
int i = 1;
if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &i, sizeof i) == -1)
{
fprintf(stderr, MOCK "sockopt( SO_NOSIGPIPE)(macOS): %s\n", strerror(errno));
perror("sockopt(SO_NOSIGPIPE)(macOS)");
close(sock);
return -1;
}
#endif
Expand Down Expand Up @@ -84,6 +85,13 @@ ssize_t mockFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize)
{
size_t maxread = CCBUFSIZE - ccinbufsize;
ssize_t ret = ::read(sock, ccinbuf + ccinbufsize, maxread);

if (ret == 0)
{
// connection closed
return -1;
}

if (ret == -1)
{
if (errno != EAGAIN)
Expand All @@ -100,7 +108,7 @@ ssize_t mockFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize)
ssize_t mockPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
{
if (usersize > CCBUFSIZE)
fprintf(stderr, MOCK "CCBUFSIZE(%d) should be increased by %zd bytes (-> %zd)\n", CCBUFSIZE, usersize - CCBUFSIZE, usersize);
mockverbose("CCBUFSIZE(%d) should be increased by %zd bytes (-> %zd)\n", CCBUFSIZE, usersize - CCBUFSIZE, usersize);

struct pollfd p;
size_t retsize = 0;
Expand Down Expand Up @@ -163,12 +171,12 @@ ssize_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms)
#endif
if (ret == -1)
{
fprintf(stderr, MOCK "ClientContext::read: write(%d): %s\n", sock, strerror(errno));
fprintf(stderr, MOCK "ClientContext::write(%d): %s\n", sock, strerror(errno));
return -1;
}
if (ret != (int)size)
{
fprintf(stderr, MOCK "ClientContext::write: short write (%d < %zd) (TODO)\n", ret, size);
fprintf(stderr, MOCK "ClientContext::write: short write (%d < %zd) (FIXME poll loop TODO)\n", ret, size);
exit(EXIT_FAILURE);
}
}
Expand Down
26 changes: 11 additions & 15 deletions tests/host/common/HostWiring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@

#include <Arduino.h>

#ifdef DEBUG_ESP_CORE
#define VERBOSE(x...) fprintf(stderr, MOCK x)
#else
#define VERBOSE(x...) mockverbose(x)
#endif

void pinMode (uint8_t pin, uint8_t mode)
{
#define xxx(mode) case mode: m=STRHELPER(mode); break
Expand All @@ -46,23 +52,17 @@ void pinMode (uint8_t pin, uint8_t mode)
case WAKEUP_PULLDOWN: m="WAKEUP_PULLDOWN"; break;
default: m="(special)";
}
#ifdef DEBUG_ESP_CORE
fprintf(stderr, MOCK "gpio%d: mode='%s'\n", pin, m);
#endif
VERBOSE("gpio%d: mode='%s'\n", pin, m);
}

void digitalWrite(uint8_t pin, uint8_t val)
{
#ifdef DEBUG_ESP_CORE
fprintf(stderr, MOCK "digitalWrite(pin=%d val=%d)\n", pin, val);
#endif
VERBOSE("digitalWrite(pin=%d val=%d)\n", pin, val);
}

void analogWrite(uint8_t pin, int val)
{
#ifdef DEBUG_ESP_CORE
fprintf(stderr, MOCK "analogWrite(pin=%d, val=%d\n", pin, val);
#endif
VERBOSE("analogWrite(pin=%d, val=%d\n", pin, val);
}

int analogRead(uint8_t pin)
Expand All @@ -73,16 +73,12 @@ int analogRead(uint8_t pin)

void analogWriteRange(uint32_t range)
{
#ifdef DEBUG_ESP_CORE
fprintf(stderr, MOCK "analogWriteRange(range=%d)\n", range);
#endif
VERBOSE("analogWriteRange(range=%d)\n", range);
}

int digitalRead(uint8_t pin)
{
#ifdef DEBUG_ESP_CORE
fprintf(stderr, MOCK "digitalRead(%d)\n", pin);
#endif
VERBOSE("digitalRead(%d)\n", pin);

// pin 0 is most likely a low active input
return pin ? 0 : 1;
Expand Down
2 changes: 1 addition & 1 deletion tests/host/common/MockEsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ EspClass ESP;

void EspClass::restart ()
{
fprintf(stderr, MOCK "Esp.restart(): exiting\n");
mockverbose("Esp.restart(): exiting\n");
exit(EXIT_SUCCESS);
}

Expand Down
2 changes: 1 addition & 1 deletion tests/host/common/MockTools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ extern "C" void configTime(long timezone, int daylightOffset_sec,
(void)server2;
(void)server3;

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

void stack_thunk_add_ref() { }
Expand Down
12 changes: 0 additions & 12 deletions tests/host/common/MockWiFiServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,11 @@ extern "C" const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY);
WiFiServer::WiFiServer (const IPAddress& addr, uint16_t port)
{
(void)addr;
if (port < 1024)
{
int newport = port + 9000;
fprintf(stderr, MOCK "WiFiServer port: %d -> %d\n", port, newport);
port = newport;
}
_port = port;
}

WiFiServer::WiFiServer (uint16_t port)
{
if (port < 1024)
{
int newport = port + 9000;
fprintf(stderr, MOCK "WiFiServer port: %d -> %d\n", port, newport);
port = newport;
}
_port = port;
}

Expand Down
13 changes: 12 additions & 1 deletion tests/host/common/MockWiFiServerSocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,18 @@ void WiFiServer::begin (uint16_t port)
void WiFiServer::begin ()
{
int sock;
int mockport;
struct sockaddr_in server;

mockport = _port;
if (mockport < 1024 && mock_port_shifter)
{
mockport += mock_port_shifter;
fprintf(stderr, MOCK "=====> WiFiServer port: %d shifted to %d (use option -s) <=====\n", _port, mockport);
}
else
fprintf(stderr, MOCK "=====> WiFiServer port: %d <=====\n", mockport);

if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror(MOCK "socket()");
Expand All @@ -83,7 +93,7 @@ void WiFiServer::begin ()
}

server.sin_family = AF_INET;
server.sin_port = htons(_port);
server.sin_port = htons(mockport);
server.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock, (struct sockaddr*)&server, sizeof(server)) == -1)
{
Expand Down Expand Up @@ -118,6 +128,7 @@ size_t WiFiServer::write (uint8_t c)
size_t WiFiServer::write (const uint8_t *buf, size_t size)
{
fprintf(stderr, MOCK "todo: WiFiServer::write(%p, %zd)\n", buf, size);
exit(EXIT_FAILURE);
return 0;
}

Expand Down
Loading