Skip to content

Commit 6bd26a3

Browse files
authored
host emulation: improve udp, persistent spiffs (#5605)
1 parent 8a64a12 commit 6bd26a3

16 files changed

+266
-142
lines changed

libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
1818
upload the contents of the data folder with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE)
1919
or you can upload the contents of a folder if you CD in that folder and run the following command:
20-
for file in `ls -A1`; do curl -F "file=@$PWD/$file" esp8266fs.local/edit; done
20+
for file in `\ls -A1`; do curl -F "file=@$PWD/$file" esp8266fs.local/edit; done
2121
2222
access the sample web page at http://esp8266fs.local
2323
edit the page by going to http://esp8266fs.local/edit

tests/host/Makefile

+4-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ LCOV ?= lcov
1919
GENHTML ?= genhtml
2020

2121
ifeq ($(FORCE32),1)
22-
ABILITY32 = $(shell echo 'int main(){return sizeof(long);}'|$(CXX) -m32 -x c++ - -o sizeoflong 2>/dev/null && ./sizeoflong; echo $$?; rm -f sizeoflong;)
23-
ifneq ($(ABILITY32),4)
22+
SIZEOFLONG = $(shell echo 'int main(){return sizeof(long);}'|$(CXX) -m32 -x c++ - -o sizeoflong 2>/dev/null && ./sizeoflong; echo $$?; rm -f sizeoflong;)
23+
ifneq ($(SIZEOFLONG),4)
2424
$(warning Cannot compile in 32 bit mode, switching to native mode)
2525
else
2626
N32 = 32
@@ -82,6 +82,8 @@ MOCK_CPP_FILES := $(MOCK_CPP_FILES_COMMON) $(addprefix common/,\
8282

8383
MOCK_CPP_FILES_EMU := $(MOCK_CPP_FILES_COMMON) $(addprefix common/,\
8484
ArduinoMain.cpp \
85+
ArduinoMainUdp.cpp \
86+
ArduinoMainSpiffs.cpp \
8587
user_interface.cpp \
8688
)
8789

tests/host/common/ArduinoMain.cpp

+45-45
Original file line numberDiff line numberDiff line change
@@ -32,37 +32,13 @@
3232
#include <Arduino.h>
3333
#include <user_interface.h> // wifi_get_ip_info()
3434

35-
#include <functional>
36-
#include "lwip/opt.h"
37-
#include "lwip/udp.h"
38-
#include "lwip/inet.h"
39-
#include "lwip/igmp.h"
40-
#include "lwip/mem.h"
41-
#include <include/UdpContext.h>
42-
#include <poll.h>
43-
35+
#include <signal.h>
4436
#include <unistd.h> // usleep
4537
#include <getopt.h>
4638

47-
#include <map>
48-
49-
#if 0
50-
#include "../common/spiffs_mock.h"
51-
#include <spiffs/spiffs.h>
52-
SPIFFS_MOCK_DECLARE(/*size_kb*/1024, /(blovk_kb*/8, /*page_b*/512);
53-
#endif
54-
55-
std::map<int,UdpContext*> udps;
56-
57-
void register_udp (int sock, UdpContext* udp)
58-
{
59-
if (udp)
60-
udps[sock] = udp;
61-
else
62-
udps.erase(sock);
63-
}
64-
39+
bool user_exit = false;
6540
const char* host_interface = nullptr;
41+
size_t spiffs_kb = 1024;
6642

6743
void help (const char* argv0, int exitcode)
6844
{
@@ -73,7 +49,9 @@ void help (const char* argv0, int exitcode)
7349
" -i <interface> - use this interface for IP address\n"
7450
" -l - bind tcp/udp servers to interface only (not 0.0.0.0)\n"
7551
" -f - no throttle (possibly 100%%CPU)\n"
76-
, argv0);
52+
" -S - spiffs size in KBytes (default: %zd)\n"
53+
" (negative value will force mismatched size)\n"
54+
, argv0, spiffs_kb);
7755
exit(exitcode);
7856
}
7957

@@ -83,15 +61,36 @@ static struct option options[] =
8361
{ "fast", no_argument, NULL, 'f' },
8462
{ "local", no_argument, NULL, 'l' },
8563
{ "interface", required_argument, NULL, 'i' },
64+
{ "spiffskb", required_argument, NULL, 'S' },
8665
};
8766

67+
void save ()
68+
{
69+
mock_stop_spiffs();
70+
}
71+
72+
void control_c (int sig)
73+
{
74+
(void)sig;
75+
76+
if (user_exit)
77+
{
78+
fprintf(stderr, MOCK "stuck, killing\n");
79+
save();
80+
exit(1);
81+
}
82+
user_exit = true;
83+
}
84+
8885
int main (int argc, char* const argv [])
8986
{
87+
signal(SIGINT, control_c);
88+
9089
bool fast = false;
9190

9291
for (;;)
9392
{
94-
int n = getopt_long(argc, argv, "hlfi:", options, NULL);
93+
int n = getopt_long(argc, argv, "hlfi:S:", options, NULL);
9594
if (n < 0)
9695
break;
9796
switch (n)
@@ -108,36 +107,37 @@ int main (int argc, char* const argv [])
108107
case 'f':
109108
fast = true;
110109
break;
110+
case 'S':
111+
spiffs_kb = atoi(optarg);
112+
break;
111113
default:
112114
fprintf(stderr, MOCK "bad option '%c'\n", n);
113115
exit(EXIT_FAILURE);
114116
}
115117
}
116118

119+
if (spiffs_kb)
120+
{
121+
String name = argv[0];
122+
name += "-spiffs";
123+
name += String(spiffs_kb > 0? spiffs_kb: -spiffs_kb, DEC);
124+
name += "KB";
125+
mock_start_spiffs(name, spiffs_kb);
126+
}
127+
117128
// setup global global_ipv4_netfmt
118129
wifi_get_ip_info(0, nullptr);
119130

120131
setup();
121-
while (true)
132+
while (!user_exit)
122133
{
123134
if (!fast)
124135
usleep(10000); // not 100% cpu
125-
126136
loop();
127-
128-
// check incoming udp
129-
for (auto& udp: udps)
130-
{
131-
pollfd p;
132-
p.fd = udp.first;
133-
p.events = POLLIN;
134-
if (poll(&p, 1, 0) && p.revents == POLLIN)
135-
{
136-
fprintf(stderr, MOCK "UDP poll(%d) -> cb\r", p.fd);
137-
udp.second->mock_cb();
138-
}
139-
}
137+
check_incoming_udp();
140138
}
139+
140+
save();
141+
141142
return 0;
142143
}
143-
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
#include "spiffs_mock.h"
3+
4+
SpiffsMock* spiffs_mock = nullptr;
5+
6+
void mock_start_spiffs (const String& fname, size_t size_kb, size_t block_kb, size_t page_b)
7+
{
8+
spiffs_mock = new SpiffsMock(size_kb * 1024, block_kb * 1024, page_b, fname);
9+
}
10+
11+
void mock_stop_spiffs ()
12+
{
13+
if (spiffs_mock)
14+
delete spiffs_mock;
15+
spiffs_mock = nullptr;
16+
}
17+

tests/host/common/ArduinoMainUdp.cpp

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
Arduino emulator main loop
3+
Copyright (c) 2018 david gauchard. All rights reserved.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a
6+
copy of this software and associated documentation files (the "Software"),
7+
to deal with the Software without restriction, including without limitation
8+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
9+
and/or sell copies of the Software, and to permit persons to whom the
10+
Software is furnished to do so, subject to the following conditions:
11+
12+
- Redistributions of source code must retain the above copyright notice,
13+
this list of conditions and the following disclaimers.
14+
15+
- Redistributions in binary form must reproduce the above copyright notice,
16+
this list of conditions and the following disclaimers in the
17+
documentation and/or other materials provided with the distribution.
18+
19+
- The names of its contributors may not be used to endorse or promote
20+
products derived from this Software without specific prior written
21+
permission.
22+
23+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26+
THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
27+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29+
DEALINGS WITH THE SOFTWARE.
30+
*/
31+
32+
#include "lwip/opt.h"
33+
#include "lwip/udp.h"
34+
#include "lwip/inet.h"
35+
#include "lwip/igmp.h"
36+
#include "lwip/mem.h"
37+
#include <include/UdpContext.h>
38+
#include <poll.h>
39+
#include <map>
40+
41+
std::map<int,UdpContext*> udps;
42+
43+
void register_udp (int sock, UdpContext* udp)
44+
{
45+
if (udp)
46+
udps[sock] = udp;
47+
else
48+
udps.erase(sock);
49+
}
50+
51+
void check_incoming_udp ()
52+
{
53+
// check incoming udp
54+
for (auto& udp: udps)
55+
{
56+
pollfd p;
57+
p.fd = udp.first;
58+
p.events = POLLIN;
59+
if (poll(&p, 1, 0) && p.revents == POLLIN)
60+
{
61+
fprintf(stderr, MOCK "UDP poll(%d) -> cb\r", p.fd);
62+
udp.second->mock_cb();
63+
}
64+
}
65+
}

tests/host/common/ClientContextSocket.cpp

+16-9
Original file line numberDiff line numberDiff line change
@@ -66,20 +66,24 @@ int mockConnect (uint32_t ipv4, int& sock, int port)
6666
return 1;
6767
}
6868

69-
size_t mockFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize)
69+
ssize_t mockFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize)
7070
{
7171
size_t maxread = CCBUFSIZE - ccinbufsize;
7272
ssize_t ret = ::read(sock, ccinbuf + ccinbufsize, maxread);
7373
if (ret == -1)
7474
{
7575
if (errno != EAGAIN)
76-
fprintf(stderr, MOCK "ClientContext::(read/peek): filling buffer for %zd bytes: %s\n", maxread, strerror(errno));
76+
{
77+
fprintf(stderr, MOCK "ClientContext::(read/peek fd=%i): filling buffer for %zd bytes: %s\n", sock, maxread, strerror(errno));
78+
return -1;
79+
}
7780
ret = 0;
7881
}
79-
return ccinbufsize += ret;
82+
ccinbufsize += ret;
83+
return ret;
8084
}
8185

82-
size_t mockPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
86+
ssize_t mockPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
8387
{
8488
if (usersize > CCBUFSIZE)
8589
fprintf(stderr, MOCK "CCBUFSIZE(%d) should be increased by %zd bytes (-> %zd)\n", CCBUFSIZE, usersize - CCBUFSIZE, usersize);
@@ -96,7 +100,8 @@ size_t mockPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char
96100
}
97101

98102
// check incoming data data
99-
mockFillInBuf(sock, ccinbuf, ccinbufsize);
103+
if (mockFillInBuf(sock, ccinbuf, ccinbufsize) < 0)
104+
return -1;
100105
if (usersize <= ccinbufsize)
101106
{
102107
// data just received
@@ -113,16 +118,18 @@ size_t mockPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char
113118
return retsize;
114119
}
115120

116-
size_t mockRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
121+
ssize_t mockRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
117122
{
118-
size_t copied = mockPeekBytes(sock, dst, size, timeout_ms, ccinbuf, ccinbufsize);
123+
ssize_t copied = mockPeekBytes(sock, dst, size, timeout_ms, ccinbuf, ccinbufsize);
124+
if (copied < 0)
125+
return -1;
119126
// swallow (XXX use a circular buffer)
120127
memmove(ccinbuf, ccinbuf + copied, ccinbufsize - copied);
121128
ccinbufsize -= copied;
122129
return copied;
123130
}
124131

125-
size_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms)
132+
ssize_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms)
126133
{
127134
struct pollfd p;
128135
p.fd = sock;
@@ -140,7 +147,7 @@ size_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms)
140147
if (ret == -1)
141148
{
142149
fprintf(stderr, MOCK "ClientContext::read: write(%d): %s\n", sock, strerror(errno));
143-
return 0;
150+
return -1;
144151
}
145152
if (ret != (int)size)
146153
{

tests/host/common/MockSerial.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ HardwareSerial::HardwareSerial (int uart_nr)
4040
{
4141
if (uart_nr != 0)
4242
fprintf(stderr, MOCK "FIXME HardwareSerial::HardwareSerial(%d)\n", uart_nr);
43+
_uart = (decltype(_uart))1; // not used, for 'while (!Serial);' to pass
4344
}
4445

4546
void HardwareSerial::begin (unsigned long baud, SerialConfig config, SerialMode mode, uint8_t tx_pin)

tests/host/common/UdpContextSocket.cpp

+8-3
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,17 @@ size_t mockUDPPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, c
150150
return retsize;
151151
}
152152

153-
size_t mockUDPRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
153+
void mockUDPSwallow (size_t copied, char* ccinbuf, size_t& ccinbufsize)
154154
{
155-
size_t copied = mockUDPPeekBytes(sock, dst, size, timeout_ms, ccinbuf, ccinbufsize);
156-
// swallow (XXX use a circular buffer?)
155+
// poor man buffer
157156
memmove(ccinbuf, ccinbuf + copied, ccinbufsize - copied);
158157
ccinbufsize -= copied;
158+
}
159+
160+
size_t mockUDPRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf, size_t& ccinbufsize)
161+
{
162+
size_t copied = mockUDPPeekBytes(sock, dst, size, timeout_ms, ccinbuf, ccinbufsize);
163+
mockUDPSwallow(copied, ccinbuf, ccinbufsize);
159164
return copied;
160165
}
161166

tests/host/common/esp8266_peri.h

+2
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@
33
#define FAKE_ESP8266_PERI_H
44

55
const int GPI = 0;
6+
const int GPO = 0;
7+
const int GP16I = 0;
68

79
#endif

0 commit comments

Comments
 (0)