diff --git a/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino b/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino index ff4204476f..cf1c3786d9 100644 --- a/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino +++ b/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino @@ -17,7 +17,7 @@ upload the contents of the data folder with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE) or you can upload the contents of a folder if you CD in that folder and run the following command: - for file in `ls -A1`; do curl -F "file=@$PWD/$file" esp8266fs.local/edit; done + for file in `\ls -A1`; do curl -F "file=@$PWD/$file" esp8266fs.local/edit; done access the sample web page at http://esp8266fs.local edit the page by going to http://esp8266fs.local/edit diff --git a/tests/host/Makefile b/tests/host/Makefile index a795dcc68c..5f8285374e 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -19,8 +19,8 @@ LCOV ?= lcov GENHTML ?= genhtml ifeq ($(FORCE32),1) -ABILITY32 = $(shell echo 'int main(){return sizeof(long);}'|$(CXX) -m32 -x c++ - -o sizeoflong 2>/dev/null && ./sizeoflong; echo $$?; rm -f sizeoflong;) -ifneq ($(ABILITY32),4) +SIZEOFLONG = $(shell echo 'int main(){return sizeof(long);}'|$(CXX) -m32 -x c++ - -o sizeoflong 2>/dev/null && ./sizeoflong; echo $$?; rm -f sizeoflong;) +ifneq ($(SIZEOFLONG),4) $(warning Cannot compile in 32 bit mode, switching to native mode) else N32 = 32 @@ -82,6 +82,8 @@ MOCK_CPP_FILES := $(MOCK_CPP_FILES_COMMON) $(addprefix common/,\ MOCK_CPP_FILES_EMU := $(MOCK_CPP_FILES_COMMON) $(addprefix common/,\ ArduinoMain.cpp \ + ArduinoMainUdp.cpp \ + ArduinoMainSpiffs.cpp \ user_interface.cpp \ ) diff --git a/tests/host/common/ArduinoMain.cpp b/tests/host/common/ArduinoMain.cpp index 900b865aef..54420d9e2a 100644 --- a/tests/host/common/ArduinoMain.cpp +++ b/tests/host/common/ArduinoMain.cpp @@ -32,37 +32,13 @@ #include #include // wifi_get_ip_info() -#include -#include "lwip/opt.h" -#include "lwip/udp.h" -#include "lwip/inet.h" -#include "lwip/igmp.h" -#include "lwip/mem.h" -#include -#include - +#include #include // usleep #include -#include - -#if 0 -#include "../common/spiffs_mock.h" -#include -SPIFFS_MOCK_DECLARE(/*size_kb*/1024, /(blovk_kb*/8, /*page_b*/512); -#endif - -std::map udps; - -void register_udp (int sock, UdpContext* udp) -{ - if (udp) - udps[sock] = udp; - else - udps.erase(sock); -} - +bool user_exit = false; const char* host_interface = nullptr; +size_t spiffs_kb = 1024; void help (const char* argv0, int exitcode) { @@ -73,7 +49,9 @@ void help (const char* argv0, int exitcode) " -i - use this interface for IP address\n" " -l - bind tcp/udp servers to interface only (not 0.0.0.0)\n" " -f - no throttle (possibly 100%%CPU)\n" - , argv0); + " -S - spiffs size in KBytes (default: %zd)\n" + " (negative value will force mismatched size)\n" + , argv0, spiffs_kb); exit(exitcode); } @@ -83,15 +61,36 @@ static struct option options[] = { "fast", no_argument, NULL, 'f' }, { "local", no_argument, NULL, 'l' }, { "interface", required_argument, NULL, 'i' }, + { "spiffskb", required_argument, NULL, 'S' }, }; +void save () +{ + mock_stop_spiffs(); +} + +void control_c (int sig) +{ + (void)sig; + + if (user_exit) + { + fprintf(stderr, MOCK "stuck, killing\n"); + save(); + exit(1); + } + user_exit = true; +} + int main (int argc, char* const argv []) { + signal(SIGINT, control_c); + bool fast = false; for (;;) { - int n = getopt_long(argc, argv, "hlfi:", options, NULL); + int n = getopt_long(argc, argv, "hlfi:S:", options, NULL); if (n < 0) break; switch (n) @@ -108,36 +107,37 @@ int main (int argc, char* const argv []) case 'f': fast = true; break; + case 'S': + spiffs_kb = atoi(optarg); + break; default: fprintf(stderr, MOCK "bad option '%c'\n", n); exit(EXIT_FAILURE); } } + if (spiffs_kb) + { + String name = argv[0]; + name += "-spiffs"; + name += String(spiffs_kb > 0? spiffs_kb: -spiffs_kb, DEC); + name += "KB"; + mock_start_spiffs(name, spiffs_kb); + } + // setup global global_ipv4_netfmt wifi_get_ip_info(0, nullptr); setup(); - while (true) + while (!user_exit) { if (!fast) usleep(10000); // not 100% cpu - loop(); - - // check incoming udp - for (auto& udp: udps) - { - pollfd p; - p.fd = udp.first; - p.events = POLLIN; - if (poll(&p, 1, 0) && p.revents == POLLIN) - { - fprintf(stderr, MOCK "UDP poll(%d) -> cb\r", p.fd); - udp.second->mock_cb(); - } - } + check_incoming_udp(); } + + save(); + return 0; } - diff --git a/tests/host/common/ArduinoMainSpiffs.cpp b/tests/host/common/ArduinoMainSpiffs.cpp new file mode 100644 index 0000000000..1e5099d0ff --- /dev/null +++ b/tests/host/common/ArduinoMainSpiffs.cpp @@ -0,0 +1,17 @@ + +#include "spiffs_mock.h" + +SpiffsMock* spiffs_mock = nullptr; + +void mock_start_spiffs (const String& fname, size_t size_kb, size_t block_kb, size_t page_b) +{ + spiffs_mock = new SpiffsMock(size_kb * 1024, block_kb * 1024, page_b, fname); +} + +void mock_stop_spiffs () +{ + if (spiffs_mock) + delete spiffs_mock; + spiffs_mock = nullptr; +} + diff --git a/tests/host/common/ArduinoMainUdp.cpp b/tests/host/common/ArduinoMainUdp.cpp new file mode 100644 index 0000000000..99f567fe50 --- /dev/null +++ b/tests/host/common/ArduinoMainUdp.cpp @@ -0,0 +1,65 @@ +/* + Arduino emulator main loop + Copyright (c) 2018 david gauchard. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal with the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + - The names of its contributors may not be used to endorse or promote + products derived from this Software without specific prior written + permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS WITH THE SOFTWARE. +*/ + +#include "lwip/opt.h" +#include "lwip/udp.h" +#include "lwip/inet.h" +#include "lwip/igmp.h" +#include "lwip/mem.h" +#include +#include +#include + +std::map udps; + +void register_udp (int sock, UdpContext* udp) +{ + if (udp) + udps[sock] = udp; + else + udps.erase(sock); +} + +void check_incoming_udp () +{ + // check incoming udp + for (auto& udp: udps) + { + pollfd p; + p.fd = udp.first; + p.events = POLLIN; + if (poll(&p, 1, 0) && p.revents == POLLIN) + { + fprintf(stderr, MOCK "UDP poll(%d) -> cb\r", p.fd); + udp.second->mock_cb(); + } + } +} diff --git a/tests/host/common/ClientContextSocket.cpp b/tests/host/common/ClientContextSocket.cpp index 8dd55ee62e..8778a1f49f 100644 --- a/tests/host/common/ClientContextSocket.cpp +++ b/tests/host/common/ClientContextSocket.cpp @@ -66,20 +66,24 @@ int mockConnect (uint32_t ipv4, int& sock, int port) return 1; } -size_t mockFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize) +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 == -1) { if (errno != EAGAIN) - fprintf(stderr, MOCK "ClientContext::(read/peek): filling buffer for %zd bytes: %s\n", maxread, strerror(errno)); + { + fprintf(stderr, MOCK "ClientContext::(read/peek fd=%i): filling buffer for %zd bytes: %s\n", sock, maxread, strerror(errno)); + return -1; + } ret = 0; } - return ccinbufsize += ret; + ccinbufsize += ret; + return ret; } -size_t mockPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, 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); @@ -96,7 +100,8 @@ size_t mockPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char } // check incoming data data - mockFillInBuf(sock, ccinbuf, ccinbufsize); + if (mockFillInBuf(sock, ccinbuf, ccinbufsize) < 0) + return -1; if (usersize <= ccinbufsize) { // data just received @@ -113,16 +118,18 @@ size_t mockPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char return retsize; } -size_t mockRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf, size_t& ccinbufsize) +ssize_t mockRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf, size_t& ccinbufsize) { - size_t copied = mockPeekBytes(sock, dst, size, timeout_ms, ccinbuf, ccinbufsize); + ssize_t copied = mockPeekBytes(sock, dst, size, timeout_ms, ccinbuf, ccinbufsize); + if (copied < 0) + return -1; // swallow (XXX use a circular buffer) memmove(ccinbuf, ccinbuf + copied, ccinbufsize - copied); ccinbufsize -= copied; return copied; } -size_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms) +ssize_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms) { struct pollfd p; p.fd = sock; @@ -140,7 +147,7 @@ size_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms) if (ret == -1) { fprintf(stderr, MOCK "ClientContext::read: write(%d): %s\n", sock, strerror(errno)); - return 0; + return -1; } if (ret != (int)size) { diff --git a/tests/host/common/MockSerial.cpp b/tests/host/common/MockSerial.cpp index 19790dc48b..eedcaed115 100644 --- a/tests/host/common/MockSerial.cpp +++ b/tests/host/common/MockSerial.cpp @@ -40,6 +40,7 @@ HardwareSerial::HardwareSerial (int uart_nr) { if (uart_nr != 0) fprintf(stderr, MOCK "FIXME HardwareSerial::HardwareSerial(%d)\n", uart_nr); + _uart = (decltype(_uart))1; // not used, for 'while (!Serial);' to pass } void HardwareSerial::begin (unsigned long baud, SerialConfig config, SerialMode mode, uint8_t tx_pin) diff --git a/tests/host/common/UdpContextSocket.cpp b/tests/host/common/UdpContextSocket.cpp index d30a6c1246..f257c57c94 100644 --- a/tests/host/common/UdpContextSocket.cpp +++ b/tests/host/common/UdpContextSocket.cpp @@ -150,12 +150,17 @@ size_t mockUDPPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, c return retsize; } -size_t mockUDPRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf, size_t& ccinbufsize) +void mockUDPSwallow (size_t copied, char* ccinbuf, size_t& ccinbufsize) { - size_t copied = mockUDPPeekBytes(sock, dst, size, timeout_ms, ccinbuf, ccinbufsize); - // swallow (XXX use a circular buffer?) + // poor man buffer memmove(ccinbuf, ccinbuf + copied, ccinbufsize - copied); ccinbufsize -= copied; +} + +size_t mockUDPRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf, size_t& ccinbufsize) +{ + size_t copied = mockUDPPeekBytes(sock, dst, size, timeout_ms, ccinbuf, ccinbufsize); + mockUDPSwallow(copied, ccinbuf, ccinbufsize); return copied; } diff --git a/tests/host/common/esp8266_peri.h b/tests/host/common/esp8266_peri.h index b7b17675b8..d9dfd50ed4 100644 --- a/tests/host/common/esp8266_peri.h +++ b/tests/host/common/esp8266_peri.h @@ -3,5 +3,7 @@ #define FAKE_ESP8266_PERI_H const int GPI = 0; +const int GPO = 0; +const int GP16I = 0; #endif \ No newline at end of file diff --git a/tests/host/common/include/ClientContext.h b/tests/host/common/include/ClientContext.h index 8db6c1df0d..bbd3b06882 100644 --- a/tests/host/common/include/ClientContext.h +++ b/tests/host/common/include/ClientContext.h @@ -156,18 +156,28 @@ class ClientContext size_t getSize() { - return _inbufsize?: mockFillInBuf(_sock, _inbuf, _inbufsize); + if (_sock < 0) + return 0; + if (_inbufsize) + return _inbufsize; + return mockFillInBuf(_sock, _inbuf, _inbufsize); } int read() { char c; - return read(&c, 1)? c: -1; + return read(&c, 1)? (unsigned char)c: -1; } size_t read (char* dst, size_t size) { - return mockRead(_sock, dst, size, 0, _inbuf, _inbufsize); + ssize_t ret = mockRead(_sock, dst, size, 0, _inbuf, _inbufsize); + if (ret < 0) + { + abort(); // close, CLOSED + return 0; + } + return ret; } int peek() @@ -198,7 +208,13 @@ class ClientContext size_t write(const uint8_t* data, size_t size) { - return mockWrite(_sock, data, size, _timeout_ms); + ssize_t ret = mockWrite(_sock, data, size, _timeout_ms); + if (ret < 0) + { + abort(); // close, CLOSED + return 0; + } + return ret; } size_t write(Stream& stream) @@ -208,7 +224,7 @@ class ClientContext avail = stream.readBytes(buf, avail); size_t totwrote = 0; uint8_t* w = buf; - while (avail) + while (avail && _sock >= 0) { size_t wrote = write(w, avail); w += wrote; diff --git a/tests/host/common/include/UdpContext.h b/tests/host/common/include/UdpContext.h index 572decbb3a..ebeedb0907 100644 --- a/tests/host/common/include/UdpContext.h +++ b/tests/host/common/include/UdpContext.h @@ -79,20 +79,12 @@ class UdpContext _sock = -1; } -#if 0 void setMulticastInterface(const ip_addr_t& addr) { (void)addr; // user multicast, and this is how it works with posix: send to multicast address: _dst.addr = staticMCastAddr; } -#endif - void setMulticastInterface(const ip_addr_t* addr) - { - (void)addr; - // user multicast, and this is how it works with posix: send to multicast address: - _dst.addr = staticMCastAddr; - } void setMulticastTTL(int ttl) { @@ -118,12 +110,12 @@ class UdpContext void seek(const size_t pos) { - fprintf(stderr, MOCK "TODO: implement UDP offset\n"); if (!isValidOffset(pos)) { fprintf(stderr, MOCK "UDPContext::seek too far (%zd >= %zd)\n", pos, _inbufsize); exit(EXIT_FAILURE); } + mockUDPSwallow(pos, _inbuf, _inbufsize); } bool isValidOffset(const size_t pos) const { diff --git a/tests/host/common/mock.h b/tests/host/common/mock.h index d9c6cc3b87..b48c0eda30 100644 --- a/tests/host/common/mock.h +++ b/tests/host/common/mock.h @@ -91,24 +91,26 @@ extern uint32_t global_ipv4_netfmt; // selected interface addresse to bind to #ifdef __cplusplus #ifndef CCBUFSIZE -#define CCBUFSIZE 8192 +#define CCBUFSIZE 65536 #endif // tcp -int mockConnect (uint32_t addr, int& sock, int port); -size_t mockFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize); -size_t mockPeekBytes (int sock, char* dst, size_t size, int timeout_ms, char* buf, size_t& bufsize); -size_t mockRead (int sock, char* dst, size_t size, int timeout_ms, char* buf, size_t& bufsize); -size_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms); +int mockConnect (uint32_t addr, int& sock, int port); +ssize_t mockFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize); +ssize_t mockPeekBytes (int sock, char* dst, size_t size, int timeout_ms, char* buf, size_t& bufsize); +ssize_t mockRead (int sock, char* dst, size_t size, int timeout_ms, char* buf, size_t& bufsize); +ssize_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms); int serverAccept (int sock); // udp +void check_incoming_udp (); int mockUDPSocket (); bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast = 0); size_t mockUDPFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize, uint8_t& addrsize, uint8_t addr[16], uint16_t& port); size_t mockUDPPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf, size_t& ccinbufsize); size_t mockUDPRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf, size_t& ccinbufsize); size_t mockUDPWrite (int sock, const uint8_t* data, size_t size, int timeout_ms, uint32_t ipv4, uint16_t port); +void mockUDPSwallow (size_t copied, char* ccinbuf, size_t& ccinbufsize); class UdpContext; void register_udp (int sock, UdpContext* udp = nullptr); @@ -117,6 +119,11 @@ class InterruptLock { }; // +void mock_start_spiffs (const String& fname, size_t size_kb, size_t block_kb = 8, size_t page_b = 512); +void mock_stop_spiffs (); + +// + #define CORE_MOCK 1 #define ARDUINO 267 @@ -142,4 +149,8 @@ class InterruptLock { }; // +#include + +// + #endif // __cplusplus diff --git a/tests/host/common/spiffs_mock.cpp b/tests/host/common/spiffs_mock.cpp index e63abae179..004b15fb9a 100644 --- a/tests/host/common/spiffs_mock.cpp +++ b/tests/host/common/spiffs_mock.cpp @@ -27,8 +27,6 @@ #include #include -#define SPIFFS_FILE_NAME "spiffs.bin" - extern "C" { static uint32_t s_phys_addr = 0; @@ -40,87 +38,98 @@ extern "C" FS SPIFFS(nullptr); -SpiffsMock::SpiffsMock(size_t fs_size, size_t fs_block, size_t fs_page, bool storage) +SpiffsMock::SpiffsMock(ssize_t fs_size, size_t fs_block, size_t fs_page, const String& storage) { - fprintf(stderr, "SPIFFS: %zd bytes\n", fs_size); - m_storage = storage; - m_fs = new uint8_t[m_fs_size = fs_size]; - memset(&m_fs[0], 0xff, m_fs_size); + if ((m_overwrite = (fs_size < 0))) + fs_size = -fs_size; + fprintf(stderr, "SPIFFS: %zd bytes\n", fs_size); + + m_fs.resize(fs_size, 0xff); s_phys_addr = 0; s_phys_size = static_cast(fs_size); s_phys_page = static_cast(fs_page); s_phys_block = static_cast(fs_block); - s_phys_data = &m_fs[0]; + s_phys_data = m_fs.data(); reset(); } void SpiffsMock::reset() { SPIFFS = FS(FSImplPtr(new SPIFFSImpl(0, s_phys_size, s_phys_page, s_phys_block, 5))); - if (m_storage) - load(); + load(); } SpiffsMock::~SpiffsMock() { - if (m_storage) - save(); + save(); s_phys_addr = 0; s_phys_size = 0; s_phys_page = 0; s_phys_block = 0; s_phys_data = nullptr; - delete [] m_fs; - m_fs = nullptr; - m_fs_size = 0; + m_fs.resize(0); SPIFFS = FS(FSImplPtr(nullptr)); } void SpiffsMock::load () { - if (!m_fs_size) + if (!m_fs.size() || !m_storage.length()) return; - - const char* fname = getenv("SPIFFS_PATH"); - if (!fname) - fname = DEFAULT_SPIFFS_FILE_NAME; - int fs = ::open(SPIFFS_FILE_NAME, O_RDONLY); + + int fs = ::open(m_storage.c_str(), O_RDONLY); if (fs == -1) { - fprintf(stderr, "SPIFFS: loading '%s': %s\n", fname, strerror(errno)); + fprintf(stderr, "SPIFFS: loading '%s': %s\n", m_storage.c_str(), strerror(errno)); + return; + } + + off_t flen = lseek(fs, 0, SEEK_END); + if (flen == (off_t)-1) + { + fprintf(stderr, "SPIFFS: checking size of '%s': %s\n", m_storage.c_str(), strerror(errno)); return; } - fprintf(stderr, "SPIFFS: loading %zi bytes from '%s'\n", m_fs_size, fname); - if (::read(fs, &m_fs[0], m_fs_size) != (ssize_t)m_fs_size) - fprintf(stderr, "SPIFFS: reading %zi bytes: %s\n", m_fs_size, strerror(errno)); + lseek(fs, 0, SEEK_SET); + + if (flen != (off_t)m_fs.size()) + { + fprintf(stderr, "SPIFFS: size of '%s': %d does not match requested size %zd\n", m_storage.c_str(), (int)flen, m_fs.size()); + if (!m_overwrite) + { + fprintf(stderr, "SPIFFS: aborting at user request\n"); + exit(1); + } + fprintf(stderr, "SPIFFS: continuing without loading at user request, '%s' will be overwritten\n", m_storage.c_str()); + } + else + { + fprintf(stderr, "SPIFFS: loading %zi bytes from '%s'\n", m_fs.size(), m_storage.c_str()); + ssize_t r = ::read(fs, m_fs.data(), m_fs.size()); + if (r != (ssize_t)m_fs.size()) + fprintf(stderr, "SPIFFS: reading %zi bytes: returned %zd: %s\n", m_fs.size(), r, strerror(errno)); + } ::close(fs); } void SpiffsMock::save () { - if (!m_fs_size) + if (!m_fs.size() || !m_storage.length()) return; - const char* fname = getenv("SPIFFS_PATH"); - if (!fname) - fname = DEFAULT_SPIFFS_FILE_NAME; - int fs = ::open(SPIFFS_FILE_NAME, O_CREAT | O_TRUNC | O_WRONLY, 0644); + int fs = ::open(m_storage.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644); if (fs == -1) { - fprintf(stderr, "SPIFFS: saving '%s': %s\n", fname, strerror(errno)); + fprintf(stderr, "SPIFFS: saving '%s': %s\n", m_storage.c_str(), strerror(errno)); return; } - fprintf(stderr, "SPIFFS: saving %zi bytes to '%s'\n", m_fs_size, fname); - -// this can be a valgrind error, I don't understand how it happens -//for (size_t i = 0; i < m_fs_size; i++) printf("\r%zd:%d ", i, (int)m_fs[i]); + fprintf(stderr, "SPIFFS: saving %zi bytes to '%s'\n", m_fs.size(), m_storage.c_str()); - if (::write(fs, &m_fs[0], m_fs_size) != (ssize_t)m_fs_size) - fprintf(stderr, "SPIFFS: writing %zi bytes: %s\n", m_fs_size, strerror(errno)); + if (::write(fs, m_fs.data(), m_fs.size()) != (ssize_t)m_fs.size()) + fprintf(stderr, "SPIFFS: writing %zi bytes: %s\n", m_fs.size(), strerror(errno)); if (::close(fs) == -1) - fprintf(stderr, "SPIFFS: closing %s: %s\n", fname, strerror(errno)); + fprintf(stderr, "SPIFFS: closing %s: %s\n", m_storage.c_str(), strerror(errno)); } int32_t spiffs_hal_read(uint32_t addr, uint32_t size, uint8_t *dst) { diff --git a/tests/host/common/spiffs_mock.h b/tests/host/common/spiffs_mock.h index 6b0c2c5102..a38fd820e3 100644 --- a/tests/host/common/spiffs_mock.h +++ b/tests/host/common/spiffs_mock.h @@ -25,7 +25,7 @@ class SpiffsMock { public: - SpiffsMock(size_t fs_size, size_t fs_block, size_t fs_page, bool storage = true); + SpiffsMock(ssize_t fs_size, size_t fs_block, size_t fs_page, const String& storage = emptyString); void reset(); ~SpiffsMock(); @@ -33,21 +33,12 @@ class SpiffsMock { void load (); void save (); - // it was a vector, but CI tests & valgrind complain with: - // Syscall param write(buf) points to uninitialised byte(s) - // by 0x43E9FF: SpiffsMock::save() (spiffs_mock.cpp:116) - // = if (::write(fs, &m_fs[0], m_fs_size) != (ssize_t)m_fs_size) - // so switched to a regular array - // and that bug is still here - // XXXWIPTODO - - uint8_t* m_fs; - size_t m_fs_size; - bool m_storage; + std::vector m_fs; + String m_storage; + bool m_overwrite; }; #define SPIFFS_MOCK_DECLARE(size_kb, block_kb, page_b, storage) SpiffsMock spiffs_mock(size_kb * 1024, block_kb * 1024, page_b, storage) #define SPIFFS_MOCK_RESET() spiffs_mock.reset() - #endif /* spiffs_mock_hpp */ diff --git a/tests/host/fs/test_fs.cpp b/tests/host/fs/test_fs.cpp index c97e0f718b..70103a244c 100644 --- a/tests/host/fs/test_fs.cpp +++ b/tests/host/fs/test_fs.cpp @@ -50,25 +50,25 @@ static std::set listDir (const char* path) TEST_CASE("FS can begin","[fs]") { - SPIFFS_MOCK_DECLARE(64, 8, 512, false); + SPIFFS_MOCK_DECLARE(64, 8, 512, ""); REQUIRE(SPIFFS.begin()); } TEST_CASE("FS can't begin with zero size","[fs]") { - SPIFFS_MOCK_DECLARE(0, 8, 512, false); + SPIFFS_MOCK_DECLARE(0, 8, 512, ""); REQUIRE_FALSE(SPIFFS.begin()); } TEST_CASE("Before begin is called, open will fail","[fs]") { - SPIFFS_MOCK_DECLARE(64, 8, 512, false); + SPIFFS_MOCK_DECLARE(64, 8, 512, ""); REQUIRE_FALSE(SPIFFS.open("/foo", "w")); } TEST_CASE("FS can create file","[fs]") { - SPIFFS_MOCK_DECLARE(64, 8, 512, false); + SPIFFS_MOCK_DECLARE(64, 8, 512, ""); REQUIRE(SPIFFS.begin()); createFile("/test", ""); REQUIRE(SPIFFS.exists("/test")); @@ -76,7 +76,7 @@ TEST_CASE("FS can create file","[fs]") TEST_CASE("Files can be written and appended to","[fs]") { - SPIFFS_MOCK_DECLARE(64, 8, 512, false); + SPIFFS_MOCK_DECLARE(64, 8, 512, ""); REQUIRE(SPIFFS.begin()); { File f = SPIFFS.open("config1.txt", "w"); @@ -100,7 +100,7 @@ TEST_CASE("Files can be written and appended to","[fs]") TEST_CASE("Files persist after reset", "[fs]") { - SPIFFS_MOCK_DECLARE(64, 8, 512, false); + SPIFFS_MOCK_DECLARE(64, 8, 512, ""); REQUIRE(SPIFFS.begin()); createFile("config1.txt", "file 1"); @@ -112,7 +112,7 @@ TEST_CASE("Files persist after reset", "[fs]") TEST_CASE("Filesystem is empty after format", "[fs]") { - SPIFFS_MOCK_DECLARE(64, 8, 512, false); + SPIFFS_MOCK_DECLARE(64, 8, 512, ""); REQUIRE(SPIFFS.format()); REQUIRE(SPIFFS.begin()); createFile("/1", "first"); @@ -128,7 +128,7 @@ TEST_CASE("Filesystem is empty after format", "[fs]") TEST_CASE("Dir lists all files", "[fs]") { - SPIFFS_MOCK_DECLARE(64, 8, 512, false); + SPIFFS_MOCK_DECLARE(64, 8, 512, ""); REQUIRE(SPIFFS.begin()); createFile("/empty", ""); createFile("/not_empty", "some text"); @@ -146,7 +146,7 @@ TEST_CASE("Dir lists all files", "[fs]") TEST_CASE("File names which are too long are rejected", "[fs]") { - SPIFFS_MOCK_DECLARE(64, 8, 512, false); + SPIFFS_MOCK_DECLARE(64, 8, 512, ""); REQUIRE(SPIFFS.begin()); const char* emptyName = ""; const char* longName_31 = "/234567890123456789012345678901"; @@ -164,7 +164,7 @@ TEST_CASE("File names which are too long are rejected", "[fs]") TEST_CASE("#1685 Duplicate files", "[fs][bugreport]") { - SPIFFS_MOCK_DECLARE(64, 8, 512, false); + SPIFFS_MOCK_DECLARE(64, 8, 512, ""); REQUIRE(SPIFFS.begin()); createFile("/config", "some text"); createFile("/data", ""); @@ -175,7 +175,7 @@ TEST_CASE("#1685 Duplicate files", "[fs][bugreport]") TEST_CASE("#1819 Can list all files with openDir(\"\")", "[fs][bugreport]") { - SPIFFS_MOCK_DECLARE(64, 8, 512, false); + SPIFFS_MOCK_DECLARE(64, 8, 512, ""); REQUIRE(SPIFFS.begin()); createFile("/file1", "some text"); createFile("/file2", "other text"); diff --git a/tests/run_CI_locally.sh b/tests/run_CI_locally.sh index 90b2d77c34..5b23a2e4b5 100755 --- a/tests/run_CI_locally.sh +++ b/tests/run_CI_locally.sh @@ -112,6 +112,12 @@ elif [ "$BUILD_TYPE" = "platformio_even" ]; then elif [ "$BUILD_TYPE" = "platformio_odd" ]; then BUILD_PARITY=odd tests/platformio-custom.sh +elif [ "$BUILD_TYPE" = host ]; then + tests/ci/host_test.sh + +elif [ "$BUILD_TYPE" = style ]; then + tests/ci/install_astyle.sh + else echo "BUILD_TYPE not set or invalid" exit 1