Skip to content
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