mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
Sketch emulation on host (#5342)
* WIP compile examples on host with 'make examples' * WIP bufferize tcp input * WIP Makefile * WIP network to rework, tcp/udp to factorize, udp addresses broken * minor changes to the core * WIP basic udp working * WIP mdns * WIP mcast receiving, not sending * WIP mdns OK * beta version * SSL + doc * update travis host test command * licenses * typo * doc: arduino builder is not around: declare functions before calling them * fix with latest SSL PR, compile in 32 bits mode * fix make clean * make -m32 optional * 32bits compiler ability tester * WIP * WIP (fix 1 vtable error, still another one to hunt with using spiffs) * example astyle * fix os_printf_plus * load / save mock spiffs * fix style * fix using spiffs/mock * don't mess ram * update doc * remove leftover * optimization -Os except for CI, rename ARCH32 to FORCE32 * revert useless cast (not even compiled) * remove unused function * use proper type for pointer arithmetics * makefile: sketch object and cpp file moved to bin/ directories easier to clean, and IDE don't like them * changes for review * make use of %zd * less verbose makefile by default (option) * update readme
This commit is contained in:
parent
b504881be4
commit
74ca42f829
@ -22,7 +22,7 @@
|
||||
#include "flash_utils.h"
|
||||
#include "eboot_command.h"
|
||||
#include <memory>
|
||||
#include "interrupts.h"
|
||||
#include <interrupts.h>
|
||||
#include "MD5Builder.h"
|
||||
#include "umm_malloc/umm_malloc.h"
|
||||
#include "cont.h"
|
||||
@ -165,6 +165,7 @@ void EspClass::restart(void)
|
||||
uint16_t EspClass::getVcc(void)
|
||||
{
|
||||
InterruptLock lock;
|
||||
(void)lock;
|
||||
return system_get_vdd33();
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,7 @@ public:
|
||||
|
||||
class FSImpl {
|
||||
public:
|
||||
virtual ~FSImpl () { }
|
||||
virtual bool begin() = 0;
|
||||
virtual void end() = 0;
|
||||
virtual bool format() = 0;
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include "Updater.h"
|
||||
#include "Arduino.h"
|
||||
#include "eboot_command.h"
|
||||
#include "interrupts.h"
|
||||
#include "esp8266_peri.h"
|
||||
#include <interrupts.h>
|
||||
#include <esp8266_peri.h>
|
||||
|
||||
//#define DEBUG_UPDATER Serial
|
||||
|
||||
@ -84,21 +84,21 @@ bool UpdaterClass::begin(size_t size, int command, int ledPin, uint8_t ledOn) {
|
||||
|
||||
wifi_set_sleep_type(NONE_SLEEP_T);
|
||||
|
||||
uint32_t updateStartAddress = 0;
|
||||
uintptr_t updateStartAddress = 0;
|
||||
if (command == U_FLASH) {
|
||||
//size of current sketch rounded to a sector
|
||||
uint32_t currentSketchSize = (ESP.getSketchSize() + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
|
||||
size_t currentSketchSize = (ESP.getSketchSize() + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
|
||||
//address of the end of the space available for sketch and update
|
||||
uint32_t updateEndAddress = (uint32_t)&_SPIFFS_start - 0x40200000;
|
||||
uintptr_t updateEndAddress = (uintptr_t)&_SPIFFS_start - 0x40200000;
|
||||
//size of the update rounded to a sector
|
||||
uint32_t roundedSize = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
|
||||
size_t roundedSize = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
|
||||
//address where we will start writing the update
|
||||
updateStartAddress = (updateEndAddress > roundedSize)? (updateEndAddress - roundedSize) : 0;
|
||||
|
||||
#ifdef DEBUG_UPDATER
|
||||
DEBUG_UPDATER.printf("[begin] roundedSize: 0x%08X (%d)\n", roundedSize, roundedSize);
|
||||
DEBUG_UPDATER.printf("[begin] updateEndAddress: 0x%08X (%d)\n", updateEndAddress, updateEndAddress);
|
||||
DEBUG_UPDATER.printf("[begin] currentSketchSize: 0x%08X (%d)\n", currentSketchSize, currentSketchSize);
|
||||
DEBUG_UPDATER.printf("[begin] roundedSize: 0x%08zX (%zd)\n", roundedSize, roundedSize);
|
||||
DEBUG_UPDATER.printf("[begin] updateEndAddress: 0x%08zX (%zd)\n", updateEndAddress, updateEndAddress);
|
||||
DEBUG_UPDATER.printf("[begin] currentSketchSize: 0x%08zX (%zd)\n", currentSketchSize, currentSketchSize);
|
||||
#endif
|
||||
|
||||
//make sure that the size of both sketches is less than the total space (updateEndAddress)
|
||||
@ -108,7 +108,7 @@ bool UpdaterClass::begin(size_t size, int command, int ledPin, uint8_t ledOn) {
|
||||
}
|
||||
}
|
||||
else if (command == U_SPIFFS) {
|
||||
updateStartAddress = (uint32_t)&_SPIFFS_start - 0x40200000;
|
||||
updateStartAddress = (uintptr_t)&_SPIFFS_start - 0x40200000;
|
||||
}
|
||||
else {
|
||||
// unknown command
|
||||
@ -133,7 +133,7 @@ bool UpdaterClass::begin(size_t size, int command, int ledPin, uint8_t ledOn) {
|
||||
#ifdef DEBUG_UPDATER
|
||||
DEBUG_UPDATER.printf("[begin] _startAddress: 0x%08X (%d)\n", _startAddress, _startAddress);
|
||||
DEBUG_UPDATER.printf("[begin] _currentAddress: 0x%08X (%d)\n", _currentAddress, _currentAddress);
|
||||
DEBUG_UPDATER.printf("[begin] _size: 0x%08X (%d)\n", _size, _size);
|
||||
DEBUG_UPDATER.printf("[begin] _size: 0x%08zX (%zd)\n", _size, _size);
|
||||
#endif
|
||||
|
||||
_md5.begin();
|
||||
@ -159,7 +159,7 @@ bool UpdaterClass::end(bool evenIfRemaining){
|
||||
|
||||
if(hasError() || (!isFinished() && !evenIfRemaining)){
|
||||
#ifdef DEBUG_UPDATER
|
||||
DEBUG_UPDATER.printf("premature end: res:%u, pos:%u/%u\n", getError(), progress(), _size);
|
||||
DEBUG_UPDATER.printf("premature end: res:%u, pos:%zu/%zu\n", getError(), progress(), _size);
|
||||
#endif
|
||||
|
||||
_reset();
|
||||
@ -199,10 +199,10 @@ bool UpdaterClass::end(bool evenIfRemaining){
|
||||
eboot_command_write(&ebcmd);
|
||||
|
||||
#ifdef DEBUG_UPDATER
|
||||
DEBUG_UPDATER.printf("Staged: address:0x%08X, size:0x%08X\n", _startAddress, _size);
|
||||
DEBUG_UPDATER.printf("Staged: address:0x%08X, size:0x%08zX\n", _startAddress, _size);
|
||||
}
|
||||
else if (_command == U_SPIFFS) {
|
||||
DEBUG_UPDATER.printf("SPIFFS: address:0x%08X, size:0x%08X\n", _startAddress, _size);
|
||||
DEBUG_UPDATER.printf("SPIFFS: address:0x%08X, size:0x%08zX\n", _startAddress, _size);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -109,6 +109,7 @@ bool isSpiffsFilenameValid(const char* name)
|
||||
}
|
||||
|
||||
// these symbols should be defined in the linker script for each flash layout
|
||||
#ifndef CORE_MOCK
|
||||
#ifdef ARDUINO
|
||||
extern "C" uint32_t _SPIFFS_start;
|
||||
extern "C" uint32_t _SPIFFS_end;
|
||||
@ -131,6 +132,7 @@ FS SPIFFS = FS(FSImplPtr(new SPIFFSImpl(
|
||||
SPIFFS_PHYS_PAGE,
|
||||
SPIFFS_PHYS_BLOCK,
|
||||
SPIFFS_MAX_OPEN_FILES)));
|
||||
#endif
|
||||
#endif // ARDUINO
|
||||
#endif // !CORE_MOCK
|
||||
|
||||
#endif
|
||||
|
@ -220,7 +220,7 @@ protected:
|
||||
size_t cacheBufSize = SPIFFS_buffer_bytes_for_cache(&_fs, _maxOpenFds);
|
||||
|
||||
if (!_workBuf) {
|
||||
DEBUGV("SPIFFSImpl: allocating %d+%d+%d=%d bytes\r\n",
|
||||
DEBUGV("SPIFFSImpl: allocating %zd+%zd+%zd=%zd bytes\r\n",
|
||||
workBufSize, fdsBufSize, cacheBufSize,
|
||||
workBufSize + fdsBufSize + cacheBufSize);
|
||||
_workBuf.reset(new uint8_t[workBufSize]);
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
DNSServer::DNSServer()
|
||||
{
|
||||
_ttl = htonl(60);
|
||||
_ttl = lwip_htonl(60);
|
||||
_errorReplyCode = DNSReplyCode::NonExistentDomain;
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ void DNSServer::setErrorReplyCode(const DNSReplyCode &replyCode)
|
||||
|
||||
void DNSServer::setTTL(const uint32_t &ttl)
|
||||
{
|
||||
_ttl = htonl(ttl);
|
||||
_ttl = lwip_htonl(ttl);
|
||||
}
|
||||
|
||||
void DNSServer::stop()
|
||||
@ -81,7 +81,7 @@ void DNSServer::processNextRequest()
|
||||
|
||||
bool DNSServer::requestIncludesOnlyOneQuestion(const DNSHeader* dnsHeader)
|
||||
{
|
||||
return ntohs(dnsHeader->QDCount) == 1 &&
|
||||
return lwip_ntohs(dnsHeader->QDCount) == 1 &&
|
||||
dnsHeader->ANCount == 0 &&
|
||||
dnsHeader->NSCount == 0 &&
|
||||
dnsHeader->ARCount == 0;
|
||||
|
@ -734,7 +734,7 @@ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size)
|
||||
free(buff);
|
||||
|
||||
if(size && (int) size != bytesWritten) {
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] Stream payload bytesWritten %d and size %d mismatch!.\n", bytesWritten, size);
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] Stream payload bytesWritten %d and size %zd mismatch!.\n", bytesWritten, size);
|
||||
DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] ERROR SEND PAYLOAD FAILED!");
|
||||
return returnError(HTTPC_ERROR_SEND_PAYLOAD_FAILED);
|
||||
} else {
|
||||
|
@ -438,12 +438,9 @@ void ESP8266WebServer::sendContent(const String& content) {
|
||||
const char * footer = "\r\n";
|
||||
size_t len = content.length();
|
||||
if(_chunked) {
|
||||
char * chunkSize = (char *)malloc(11);
|
||||
if(chunkSize){
|
||||
sprintf(chunkSize, "%x%s", len, footer);
|
||||
_currentClientWrite(chunkSize, strlen(chunkSize));
|
||||
free(chunkSize);
|
||||
}
|
||||
char chunkSize[11];
|
||||
sprintf(chunkSize, "%zx\r\n", len);
|
||||
_currentClientWrite(chunkSize, strlen(chunkSize));
|
||||
}
|
||||
_currentClientWrite(content.c_str(), len);
|
||||
if(_chunked){
|
||||
@ -461,12 +458,9 @@ void ESP8266WebServer::sendContent_P(PGM_P content) {
|
||||
void ESP8266WebServer::sendContent_P(PGM_P content, size_t size) {
|
||||
const char * footer = "\r\n";
|
||||
if(_chunked) {
|
||||
char * chunkSize = (char *)malloc(11);
|
||||
if(chunkSize){
|
||||
sprintf(chunkSize, "%x%s", size, footer);
|
||||
_currentClientWrite(chunkSize, strlen(chunkSize));
|
||||
free(chunkSize);
|
||||
}
|
||||
char chunkSize[11];
|
||||
sprintf(chunkSize, "%zx\r\n", size);
|
||||
_currentClientWrite(chunkSize, strlen(chunkSize));
|
||||
}
|
||||
_currentClientWrite_P(content, size);
|
||||
if(_chunked){
|
||||
|
80
libraries/ESP8266WiFi/examples/udp/udp.ino
Normal file
80
libraries/ESP8266WiFi/examples/udp/udp.ino
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
UDPSendReceive.pde:
|
||||
This sketch receives UDP message strings, prints them to the serial port
|
||||
and sends an "acknowledge" string back to the sender
|
||||
|
||||
A Processing sketch is included at the end of file that can be used to send
|
||||
and received messages for testing with a computer.
|
||||
|
||||
created 21 Aug 2010
|
||||
by Michael Margolis
|
||||
|
||||
This code is in the public domain.
|
||||
|
||||
adapted from Ethernet library examples
|
||||
*/
|
||||
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiUdp.h>
|
||||
|
||||
#define SSID "ssid"
|
||||
#define PSK "psk"
|
||||
|
||||
unsigned int localPort = 8888; // local port to listen on
|
||||
|
||||
// buffers for receiving and sending data
|
||||
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,
|
||||
char ReplyBuffer[] = "acknowledged\r\n"; // a string to send back
|
||||
|
||||
WiFiUDP Udp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(SSID, PSK);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
Serial.print('.');
|
||||
delay(500);
|
||||
}
|
||||
Serial.print("Connected! IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
Serial.printf("UDP server on port %d\n", localPort);
|
||||
Udp.begin(localPort);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// if there's data available, read a packet
|
||||
int packetSize = Udp.parsePacket();
|
||||
if (packetSize) {
|
||||
Serial.print("Received packet of size ");
|
||||
Serial.println(packetSize);
|
||||
Serial.print("From ");
|
||||
IPAddress remote = Udp.remoteIP();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
Serial.print(remote[i], DEC);
|
||||
if (i < 3) {
|
||||
Serial.print(".");
|
||||
}
|
||||
}
|
||||
Serial.print(", port ");
|
||||
Serial.println(Udp.remotePort());
|
||||
|
||||
// read the packet into packetBufffer
|
||||
Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
|
||||
Serial.println("Contents:");
|
||||
Serial.println(packetBuffer);
|
||||
|
||||
// send a reply, to the IP address and port that sent us the packet we received
|
||||
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
|
||||
Udp.write(ReplyBuffer);
|
||||
Udp.endPacket();
|
||||
}
|
||||
delay(10);
|
||||
}
|
||||
|
||||
/*
|
||||
test (shell/netcat):
|
||||
---------------
|
||||
nc -u 192.168.esp.address 8888
|
||||
*/
|
@ -826,6 +826,8 @@ bool X509List::append(const uint8_t *derCert, size_t derLen) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !CORE_MOCK
|
||||
|
||||
// Second stack thunked helpers
|
||||
make_stack_thunk(br_ssl_engine_recvapp_ack);
|
||||
make_stack_thunk(br_ssl_engine_recvapp_buf);
|
||||
@ -836,4 +838,6 @@ make_stack_thunk(br_ssl_engine_sendapp_buf);
|
||||
make_stack_thunk(br_ssl_engine_sendrec_ack);
|
||||
make_stack_thunk(br_ssl_engine_sendrec_buf);
|
||||
|
||||
#endif
|
||||
|
||||
};
|
@ -38,7 +38,7 @@ extern "C"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "include/ClientContext.h"
|
||||
#include <include/ClientContext.h>
|
||||
#include "c_types.h"
|
||||
|
||||
uint16_t WiFiClient::_localPort = 0;
|
||||
|
@ -40,10 +40,12 @@ extern "C" {
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "include/ClientContext.h"
|
||||
#include <include/ClientContext.h>
|
||||
#include "c_types.h"
|
||||
#include "coredecls.h"
|
||||
|
||||
#if !CORE_MOCK
|
||||
|
||||
// The BearSSL thunks in use for now
|
||||
#define br_ssl_engine_recvapp_ack thunk_br_ssl_engine_recvapp_ack
|
||||
#define br_ssl_engine_recvapp_buf thunk_br_ssl_engine_recvapp_buf
|
||||
@ -54,6 +56,8 @@ extern "C" {
|
||||
#define br_ssl_engine_sendrec_ack thunk_br_ssl_engine_sendrec_ack
|
||||
#define br_ssl_engine_sendrec_buf thunk_br_ssl_engine_sendrec_buf
|
||||
|
||||
#endif
|
||||
|
||||
namespace BearSSL {
|
||||
|
||||
void WiFiClientSecure::_clear() {
|
||||
@ -1377,6 +1381,21 @@ bool WiFiClientSecure::loadPrivateKey(Stream& stream, size_t size) {
|
||||
// SSL debugging which should focus on the WiFiClientBearSSL objects.
|
||||
|
||||
extern "C" {
|
||||
|
||||
#if CORE_MOCK
|
||||
|
||||
void br_esp8266_stack_proxy_init(uint8_t *space, uint16_t size) {
|
||||
(void)space;
|
||||
(void)size;
|
||||
}
|
||||
void _BearSSLCheckStack(const char *fcn, const char *file, int line) {
|
||||
(void)fcn;
|
||||
(void)file;
|
||||
(void)line;
|
||||
}
|
||||
|
||||
#else // !CORE_MOCK
|
||||
|
||||
extern size_t br_esp8266_stack_proxy_usage();
|
||||
|
||||
void _BearSSLCheckStack(const char *fcn, const char *file, int line) {
|
||||
@ -1386,7 +1405,7 @@ extern "C" {
|
||||
int freeheap = ESP.getFreeHeap();
|
||||
static int laststack, lastheap, laststack2;
|
||||
if ((laststack != freestack) || (lastheap != freeheap) || (laststack2 != (int)br_esp8266_stack_proxy_usage())) {
|
||||
Serial.printf("%s:%s(%d): FREESTACK=%d, STACK2USAGE=%d, FREEHEAP=%d\n", file, fcn, line, freestack, br_esp8266_stack_proxy_usage(), freeheap);
|
||||
Serial.printf("%s:%s(%d): FREESTACK=%d, STACK2USAGE=%zd, FREEHEAP=%d\n", file, fcn, line, freestack, br_esp8266_stack_proxy_usage(), freeheap);
|
||||
if (freestack < 256) {
|
||||
Serial.printf("!!! Out of main stack space\n");
|
||||
}
|
||||
@ -1405,6 +1424,8 @@ extern "C" {
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !CORE_MOCK
|
||||
|
||||
void _BearSSLSerialPrint(const char *str) {
|
||||
static int cnt = 0;
|
||||
Serial.printf("%s", str);
|
||||
|
@ -35,7 +35,7 @@ extern "C" {
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "include/ClientContext.h"
|
||||
#include <include/ClientContext.h>
|
||||
|
||||
WiFiServer::WiFiServer(IPAddress addr, uint16_t port)
|
||||
: _port(port)
|
||||
|
@ -34,7 +34,7 @@ extern "C" {
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "include/ClientContext.h"
|
||||
#include <include/ClientContext.h>
|
||||
#include "WiFiServerSecureBearSSL.h"
|
||||
|
||||
namespace BearSSL {
|
||||
|
@ -38,7 +38,7 @@ extern "C"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/igmp.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "include/UdpContext.h"
|
||||
#include <include/UdpContext.h>
|
||||
|
||||
|
||||
template<>
|
||||
@ -106,7 +106,9 @@ uint8_t WiFiUDP::beginMulticast(IPAddress interfaceAddr, IPAddress multicast, ui
|
||||
|
||||
_ctx = new UdpContext;
|
||||
_ctx->ref();
|
||||
if (!_ctx->listen(*IP_ADDR_ANY, port)) {
|
||||
ip_addr_t addr;
|
||||
addr.addr = INADDR_ANY;
|
||||
if (!_ctx->listen(addr, port)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -284,7 +286,7 @@ uint16_t WiFiUDP::localPort()
|
||||
void WiFiUDP::stopAll()
|
||||
{
|
||||
for (WiFiUDP* it = _s_first; it; it = it->_next) {
|
||||
DEBUGV("%s %08x %08x\n", __func__, (uint32_t) it, (uint32_t) _s_first);
|
||||
DEBUGV("%s %p %p\n", __func__, it, _s_first);
|
||||
it->stop();
|
||||
}
|
||||
}
|
||||
@ -292,7 +294,7 @@ void WiFiUDP::stopAll()
|
||||
void WiFiUDP::stopAllExcept(WiFiUDP * exC) {
|
||||
for (WiFiUDP* it = _s_first; it; it = it->_next) {
|
||||
if (it->_ctx != exC->_ctx) {
|
||||
DEBUGV("%s %08x %08x\n", __func__, (uint32_t) it, (uint32_t) _s_first);
|
||||
DEBUGV("%s %p %p\n", __func__, it, _s_first);
|
||||
it->stop();
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ extern "C"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "include/ClientContext.h"
|
||||
#include <include/ClientContext.h>
|
||||
#include "c_types.h"
|
||||
|
||||
namespace axTLS {
|
||||
|
@ -174,7 +174,7 @@ public:
|
||||
return 0;
|
||||
|
||||
udp_hdr* udphdr = GET_UDP_HDR(_rx_buf);
|
||||
return ntohs(udphdr->src);
|
||||
return lwip_ntohs(udphdr->src);
|
||||
}
|
||||
|
||||
uint32_t getDestAddress()
|
||||
@ -252,6 +252,7 @@ public:
|
||||
|
||||
void flush()
|
||||
{
|
||||
//XXX this does not follow Arduino's flush definition
|
||||
if (!_rx_buf)
|
||||
return;
|
||||
|
||||
|
@ -431,11 +431,11 @@ MDNSTxt * MDNSResponder::_getServiceTxt(char *name, char *proto){
|
||||
for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) {
|
||||
if(servicePtr->_port > 0 && strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0){
|
||||
if (servicePtr->_txts == 0)
|
||||
return false;
|
||||
return nullptr;
|
||||
return servicePtr->_txts;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint16_t MDNSResponder::_getServiceTxtLen(char *name, char *proto){
|
||||
|
@ -134,7 +134,7 @@ function build_docs()
|
||||
function run_host_tests()
|
||||
{
|
||||
pushd host
|
||||
make
|
||||
make FORCE32=0 OPTZ=-O0 CI
|
||||
make clean-objects
|
||||
popd
|
||||
}
|
||||
|
@ -1,7 +1,12 @@
|
||||
BINARY_DIRECTORY := bin
|
||||
BINDIR := bin
|
||||
LCOV_DIRECTORY := lcov
|
||||
OUTPUT_BINARY := $(BINARY_DIRECTORY)/host_tests
|
||||
OUTPUT_BINARY := $(BINDIR)/host_tests
|
||||
CORE_PATH := ../../cores/esp8266
|
||||
FORCE32 ?= 1
|
||||
OPTZ ?= -Os
|
||||
V ?= 0
|
||||
|
||||
MAKEFILE = $(word 1, $(MAKEFILE_LIST))
|
||||
|
||||
# I wasn't able to build with clang when -coverage flag is enabled, forcing GCC on OS X
|
||||
ifeq ($(shell uname -s),Darwin)
|
||||
@ -13,6 +18,36 @@ VALGRIND ?= valgrind
|
||||
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)
|
||||
$(warning Cannot compile in 32 bit mode, switching to native mode)
|
||||
else
|
||||
N32 = 32
|
||||
M32 = -m32
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(N32),32)
|
||||
$(warning compiling in 32 bits mode)
|
||||
else
|
||||
$(warning compiling in native mode)
|
||||
endif
|
||||
|
||||
ifeq ($(V), 0)
|
||||
VERBC = @echo "C $@";
|
||||
VERBCXX = @echo "C++ $@";
|
||||
VERBLD = @echo "LD $@";
|
||||
VERBAR = @echo "AR $@";
|
||||
else
|
||||
VERBC =
|
||||
VERBCXX =
|
||||
VERBLD =
|
||||
VERBAR =
|
||||
endif
|
||||
|
||||
$(shell mkdir -p $(BINDIR))
|
||||
|
||||
CORE_CPP_FILES := $(addprefix $(CORE_PATH)/,\
|
||||
StreamString.cpp \
|
||||
Stream.cpp \
|
||||
@ -31,12 +66,24 @@ CORE_C_FILES := $(addprefix $(CORE_PATH)/,\
|
||||
spiffs/spiffs_gc.c \
|
||||
spiffs/spiffs_hydrogen.c \
|
||||
spiffs/spiffs_nucleus.c \
|
||||
libb64/cencode.c \
|
||||
)
|
||||
|
||||
MOCK_CPP_FILES := $(addprefix common/,\
|
||||
MOCK_CPP_FILES_COMMON := $(addprefix common/,\
|
||||
Arduino.cpp \
|
||||
spiffs_mock.cpp \
|
||||
WMath.cpp \
|
||||
MockSerial.cpp \
|
||||
MockTools.cpp \
|
||||
)
|
||||
|
||||
MOCK_CPP_FILES := $(MOCK_CPP_FILES_COMMON) $(addprefix common/,\
|
||||
ArduinoCatch.cpp \
|
||||
)
|
||||
|
||||
MOCK_CPP_FILES_EMU := $(MOCK_CPP_FILES_COMMON) $(addprefix common/,\
|
||||
ArduinoMain.cpp \
|
||||
user_interface.cpp \
|
||||
)
|
||||
|
||||
MOCK_C_FILES := $(addprefix common/,\
|
||||
@ -44,21 +91,40 @@ MOCK_C_FILES := $(addprefix common/,\
|
||||
noniso.c \
|
||||
)
|
||||
|
||||
INC_PATHS += $(addprefix -I, \
|
||||
INC_PATHS := $(addprefix -I,\
|
||||
common \
|
||||
$(CORE_PATH) \
|
||||
)
|
||||
|
||||
INC_PATHS += $(addprefix -I,\
|
||||
$(shell echo ../../libraries/*/src) \
|
||||
$(shell echo ../../libraries/*) \
|
||||
../../tools/sdk/include \
|
||||
../../tools/sdk/lwip2/include \
|
||||
)
|
||||
|
||||
TEST_CPP_FILES := \
|
||||
fs/test_fs.cpp \
|
||||
core/test_pgmspace.cpp \
|
||||
core/test_md5builder.cpp \
|
||||
core/test_string.cpp
|
||||
|
||||
CXXFLAGS += -std=c++11 -Wall -Werror -coverage -O0 -fno-common -g
|
||||
CFLAGS += -std=c99 -Wall -Werror -coverage -O0 -fno-common -g
|
||||
LDFLAGS += -coverage -O0
|
||||
PREINCLUDES := \
|
||||
-include common/mock.h \
|
||||
-include common/c_types.h \
|
||||
|
||||
ifneq ($(D),)
|
||||
OPTZ=-O0
|
||||
DEBUG += -DDEBUG_ESP_PORT=Serial
|
||||
DEBUG += -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_MDNS
|
||||
endif
|
||||
|
||||
CXXFLAGS += $(DEBUG) -std=c++11 -Wall -Werror -coverage $(OPTZ) -fno-common -g $(M32)
|
||||
CFLAGS += -std=c99 -Wall -Werror -coverage $(OPTZ) -fno-common -g $(M32)
|
||||
LDFLAGS += -coverage $(OPTZ) -g $(M32)
|
||||
VALGRINDFLAGS += --leak-check=full --track-origins=yes --error-limit=no --show-leak-kinds=all --error-exitcode=999
|
||||
CXXFLAGS += -Wno-error=format-security # cores/esp8266/Print.cpp:42:24: error: format not a string literal and no format arguments [-Werror=format-security] -- (os_printf_plus(not_the_best_way))
|
||||
#CXXFLAGS += -Wno-format-security # cores/esp8266/Print.cpp:42:40: warning: format not a string literal and no format arguments [-Wformat-security] -- (os_printf_plus(not_the_best_way))
|
||||
|
||||
remduplicates = $(strip $(if $1,$(firstword $1) $(call remduplicates,$(filter-out $(firstword $1),$1))))
|
||||
|
||||
@ -74,21 +140,23 @@ CPP_OBJECTS = $(CPP_OBJECTS_CORE) $(CPP_OBJECTS_TESTS)
|
||||
OBJECTS = $(C_OBJECTS) $(CPP_OBJECTS)
|
||||
COVERAGE_FILES = $(OBJECTS:.o=.gc*)
|
||||
|
||||
all: build-info $(OUTPUT_BINARY) valgrind test gcov
|
||||
all: help
|
||||
|
||||
test: $(OUTPUT_BINARY)
|
||||
CI: build-info $(OUTPUT_BINARY) valgrind test gcov # run CI
|
||||
|
||||
test: $(OUTPUT_BINARY) # run host test for CI
|
||||
$(OUTPUT_BINARY)
|
||||
|
||||
clean: clean-objects clean-coverage
|
||||
rm -rf $(BINARY_DIRECTORY)
|
||||
clean: clean-objects clean-coverage # clean everything
|
||||
rm -rf $(BINDIR)
|
||||
|
||||
clean-objects:
|
||||
rm -rf $(OBJECTS)
|
||||
rm -rf $(C_OBJECTS) $(CPP_OBJECTS_CORE) $(CPP_OBJECTS_CORE_EMU) $(CPP_OBJECTS_TESTS)
|
||||
|
||||
clean-coverage:
|
||||
rm -rf $(COVERAGE_FILES) $(LCOV_DIRECTORY) *.gcov
|
||||
|
||||
gcov: test
|
||||
gcov: test # run coverage for CI
|
||||
find $(CORE_PATH) -name "*.gcno" -exec $(GCOV) -r -pb {} +
|
||||
|
||||
valgrind: $(OUTPUT_BINARY)
|
||||
@ -98,7 +166,7 @@ valgrind: $(OUTPUT_BINARY)
|
||||
$(LCOV) --directory $(CORE_PATH) --capture --output-file $(LCOV_DIRECTORY)/app.info
|
||||
$(GENHTML) $(LCOV_DIRECTORY)/app.info -o $(LCOV_DIRECTORY)
|
||||
|
||||
build-info:
|
||||
build-info: # show toolchain version
|
||||
@echo "-------- build tools info --------"
|
||||
@echo "CC: " $(CC)
|
||||
$(CC) -v
|
||||
@ -108,18 +176,147 @@ build-info:
|
||||
$(GCOV) -v
|
||||
@echo "----------------------------------"
|
||||
|
||||
$(BINARY_DIRECTORY):
|
||||
mkdir -p $@
|
||||
-include $(BINDIR)/.*.d
|
||||
.SUFFIXES:
|
||||
|
||||
$(C_OBJECTS): %.c.o: %.c
|
||||
$(CC) $(CFLAGS) $(INC_PATHS) -c -o $@ $<
|
||||
%.c.o: %.c
|
||||
$(VERBC) $(CC) $(PREINCLUDES) $(CFLAGS) $(INC_PATHS) -MD -MF $(BINDIR)/.$(notdir $<).d -c -o $@ $<
|
||||
|
||||
$(CPP_OBJECTS): %.cpp.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) $(INC_PATHS) -c -o $@ $<
|
||||
.PRECIOUS: %.cpp.o
|
||||
%.cpp.o: %.cpp
|
||||
$(VERBCXX) $(CXX) $(PREINCLUDES) $(CXXFLAGS) $(INC_PATHS) -MD -MF $(BINDIR)/.$(notdir $<).d -c -o $@ $<
|
||||
|
||||
$(BINARY_DIRECTORY)/core.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE)
|
||||
ar -rcu $@ $(C_OBJECTS) $(CPP_OBJECTS_CORE)
|
||||
$(BINDIR)/core.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE)
|
||||
ar -rcu $@ $^
|
||||
ranlib -c $@
|
||||
|
||||
$(OUTPUT_BINARY): $(BINARY_DIRECTORY) $(CPP_OBJECTS_TESTS) $(BINARY_DIRECTORY)/core.a
|
||||
$(CXX) $(LDFLAGS) $(CPP_OBJECTS_TESTS) $(BINARY_DIRECTORY)/core.a $(LIBS) -o $(OUTPUT_BINARY)
|
||||
$(OUTPUT_BINARY): $(CPP_OBJECTS_TESTS) $(BINDIR)/core.a
|
||||
$(VERBLD) $(CXX) $(LDFLAGS) $^ -o $@
|
||||
|
||||
#################################################
|
||||
# building ino sources
|
||||
|
||||
ARDUINO_LIBS := \
|
||||
$(addprefix $(CORE_PATH)/,\
|
||||
IPAddress.cpp \
|
||||
Updater.cpp \
|
||||
) \
|
||||
$(addprefix ../../libraries/,\
|
||||
$(addprefix ESP8266WiFi/src/,\
|
||||
ESP8266WiFi.cpp \
|
||||
ESP8266WiFiAP.cpp \
|
||||
ESP8266WiFiGeneric.cpp \
|
||||
ESP8266WiFiMulti.cpp \
|
||||
ESP8266WiFiSTA-WPS.cpp \
|
||||
ESP8266WiFiSTA.cpp \
|
||||
ESP8266WiFiScan.cpp \
|
||||
WiFiClient.cpp \
|
||||
WiFiUdp.cpp \
|
||||
WiFiClientSecureBearSSL.cpp \
|
||||
WiFiServerSecureBearSSL.cpp \
|
||||
BearSSLHelpers.cpp \
|
||||
CertStoreBearSSL.cpp \
|
||||
) \
|
||||
$(addprefix ESP8266WebServer/src/,\
|
||||
ESP8266WebServer.cpp \
|
||||
Parsing.cpp \
|
||||
detail/mimetable.cpp \
|
||||
) \
|
||||
ESP8266mDNS/ESP8266mDNS.cpp \
|
||||
ArduinoOTA/ArduinoOTA.cpp \
|
||||
DNSServer/src/DNSServer.cpp \
|
||||
ESP8266AVRISP/src/ESP8266AVRISP.cpp \
|
||||
ESP8266HTTPClient/src/ESP8266HTTPClient.cpp \
|
||||
) \
|
||||
|
||||
MOCK_ARDUINO_LIBS := \
|
||||
common/ClientContextSocket.cpp \
|
||||
common/ClientContextTools.cpp \
|
||||
common/MockWiFiServerSocket.cpp \
|
||||
common/MockWiFiServer.cpp \
|
||||
common/UdpContextSocket.cpp \
|
||||
common/HostWiring.cpp \
|
||||
common/MockEsp.cpp \
|
||||
common/MockEEPROM.cpp \
|
||||
common/MockSPI.cpp \
|
||||
|
||||
CPP_SOURCES_CORE_EMU = \
|
||||
$(MOCK_CPP_FILES_EMU) \
|
||||
$(CORE_CPP_FILES) \
|
||||
$(MOCK_ARDUINO_LIBS) \
|
||||
$(ARDUINO_LIBS) \
|
||||
|
||||
|
||||
LIBSSLFILE = ../../tools/sdk/ssl/bearssl/build$(N32)/libbearssl.a
|
||||
ifeq (,$(wildcard $(LIBSSLFILE)))
|
||||
LIBSSL =
|
||||
else
|
||||
LIBSSL = $(LIBSSLFILE)
|
||||
endif
|
||||
ssl: # download source and build BearSSL
|
||||
cd ../../tools/sdk/ssl && make native$(N32)
|
||||
|
||||
ULIBPATHS = $(shell echo $(ULIBDIRS) | sed 's,:, ,g')
|
||||
USERLIBDIRS = $(shell test -z "$(ULIBPATHS)" || for d in $(ULIBPATHS); do for dd in $$d $$d/src; do test -d $$dd && { echo -I$$dd; echo "userlib: using directory '$$dd'" 1>&2; } done; done)
|
||||
USERLIBSRCS = $(shell test -z "$(ULIBPATHS)" || for d in $(ULIBPATHS); do for ss in $$d/*.cpp $$d/src/*.cpp; do test -r $$ss && echo $$ss; done; done)
|
||||
INC_PATHS += $(USERLIBDIRS)
|
||||
CPP_OBJECTS_CORE_EMU = $(CPP_SOURCES_CORE_EMU:.cpp=.cpp.o) $(USERLIBSRCS:.cpp=.cpp.o)
|
||||
|
||||
bin/fullcore.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE_EMU)
|
||||
$(VERBAR) ar -rcu $@ $^
|
||||
$(VERBAR) ranlib -c $@
|
||||
|
||||
%: %.ino.cpp.o bin/fullcore.a
|
||||
$(VERBLD) $(CXX) $(LDFLAGS) $< bin/fullcore.a $(LIBSSL) -o $@
|
||||
@echo "----> $@ <----"
|
||||
|
||||
#################################################
|
||||
# are we in primary make call ?
|
||||
ifeq ($(INO),)
|
||||
|
||||
%: %.ino
|
||||
@# recursive 'make' with paths
|
||||
$(MAKE) -f $(MAKEFILE) INODIR=$(dir $@) INO=$(notdir $@) $(BINDIR)/$(notdir $@)/$(notdir $@)
|
||||
@# see below the new build rule with fixed output path outside from core location
|
||||
|
||||
#####################
|
||||
# recursive call on ino targer
|
||||
else
|
||||
|
||||
$(BINDIR)/$(INO)/$(INO).ino.cpp:
|
||||
@# arduino builder would come around here (.ino -> .ino.cpp)
|
||||
@mkdir -p $(BINDIR)/$(INO); \
|
||||
( \
|
||||
echo "#include \"$(INODIR)/$(INO).ino\""; \
|
||||
for i in $(INODIR)/*.ino; do \
|
||||
test "$$i" = $(INODIR)/$(INO).ino || echo "#include \"$$i\""; \
|
||||
done; \
|
||||
) > $(BINDIR)/$(INO)/$(INO).ino.cpp
|
||||
|
||||
endif # recursive
|
||||
#####################
|
||||
|
||||
#################################################
|
||||
|
||||
.PHONY: list
|
||||
list: # show core example list
|
||||
@for dir in ../../libraries/*/examples; do \
|
||||
exampledir=$${dir%/*}; \
|
||||
exampledirname=$${exampledir##*/}; \
|
||||
for subdir in $$dir/*; do \
|
||||
exname=$${subdir##*/}; \
|
||||
echo "$$subdir/$$exname"; \
|
||||
done; \
|
||||
done; \
|
||||
|
||||
#################################################
|
||||
# help
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
@cat README.txt
|
||||
@echo ""
|
||||
@echo "Make rules:"
|
||||
@echo ""
|
||||
@sed -rne 's,([^: \t]*):[^=#]*#[\t ]*(.*),\1 - \2,p' $(MAKEFILE)
|
||||
@echo ""
|
||||
|
96
tests/host/README.txt
Normal file
96
tests/host/README.txt
Normal file
@ -0,0 +1,96 @@
|
||||
|
||||
Host Tests for Continuous Integration
|
||||
-------------------------------------
|
||||
|
||||
make FORCE32=0 OPTZ=-O0 CI
|
||||
|
||||
(FORCE32=0: https://bugs.launchpad.net/ubuntu/+source/valgrind/+bug/948004)
|
||||
|
||||
Sketch emulation on host
|
||||
------------------------
|
||||
|
||||
This environment let compile esp8266/Arduino sketches into native
|
||||
environment. Network (tcp, udp, including ssl and multicast) is linked to
|
||||
local host interfaces. WiFi is trivialy emulated and reported as "just"
|
||||
already connected and usable.
|
||||
|
||||
Currently network emulation is a complete rewrite of
|
||||
WiFiClient+WiFiServer/ClientContext and WifiUdp/UdpContext using socket
|
||||
posix API. Further work will optionally propose native lwIP library
|
||||
instead.
|
||||
|
||||
How to compile and run a sketch
|
||||
-------------------------------
|
||||
|
||||
All results are stored in ./bin/ .
|
||||
|
||||
Show the core example list:
|
||||
make list
|
||||
|
||||
|
||||
Build one example
|
||||
make D=1 ../../libraries/esp8266/examples/Blink/Blink
|
||||
run it:
|
||||
./bin/Blink/Blink -h
|
||||
|
||||
|
||||
Optional 'V=1' enables makefile verbosity
|
||||
Optional 'D=1' enables core debug (same as IDE's tools menu)
|
||||
Optional 'OPTZ=-O2' will update gcc -O option (default is -Os, D=1 implies -O0)
|
||||
Optional 'FORCE32=0' will use native/default gcc (default is FORCE32=1 unless gcc-multilib is not detected)
|
||||
|
||||
|
||||
Non exhaustive list of working examples:
|
||||
make D=1 ../../libraries/ESP8266WiFi/examples/udp/udp
|
||||
make D=1 ../../libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient
|
||||
make D=1 ../../libraries/ESP8266WebServer/examples/HelloServer/HelloServer
|
||||
make D=1 ../../libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer
|
||||
make D=1 ../../libraries/ESP8266mDNS/examples/mDNS_Web_Server/mDNS_Web_Server
|
||||
make D=1 ../../libraries/ESP8266WiFi/examples/BearSSL_Validation/BearSSL_Validation
|
||||
|
||||
Compile other sketches:
|
||||
- library paths are specified using ULIBDIRS variable, separated by ':'
|
||||
- call 'make path-to-the-sketch-file' to build (without its '.ino' extension):
|
||||
- CAVEAT: functions must be declared *before* being called (arduino builder is not around)
|
||||
|
||||
make D=1 ULIBDIRS=/path/to/your/arduino/libraries/lib1:/path/to/another/place/lib2 /path/to/your/sketchdir/sketch/sketch
|
||||
or:
|
||||
ULIBDIRS=/path/to/your/arduino/libraries/lib1:/path/to/another/place/lib2 make D=1 /path/to/your/sketchdir/sketch/sketch
|
||||
|
||||
or (preferred):
|
||||
export ULIBDIRS=/path/to/your/arduino/libraries/lib1:/path/to/another/place/lib2
|
||||
export D=1
|
||||
export OPTZ=-O2
|
||||
make clean
|
||||
make /path/to/your/sketchdir/sketch/sketch
|
||||
./bin/sketch/sketch
|
||||
|
||||
|
||||
Executable location is always in bin/. Once a sketch is compiled, just run it:
|
||||
bin/sketch/sketch
|
||||
|
||||
Options are available:
|
||||
-h
|
||||
-i eth0 bind servers to this interface (WIP)
|
||||
-l bind Multicast to the above interface (WIP)
|
||||
-f no throttle (possibly 100%CPU)
|
||||
|
||||
TODO
|
||||
----
|
||||
A lot.
|
||||
Make fun, propose PRs.
|
||||
|
||||
- replace some "fprintf(stderr" with redirectable log functions
|
||||
- spiffs in a file (done, need to initialize and check)
|
||||
- EEPROM in a file (partly done)
|
||||
- SDCARD on Host filesystem ? or in an image ?
|
||||
- nice curses interface to display/change gpios ?
|
||||
- display device emulation (like ssd1306)
|
||||
- optionaly use arduino-builder ?
|
||||
- store sketch objects and binaries outside from the source directories (done for sketches)
|
||||
- compile and use lwIP on host
|
||||
- easily debug HTTP classes
|
||||
- https://github.com/esp8266/Arduino/issues/1715
|
||||
- gpio, currently:
|
||||
read as 0(digital) or 512(analog).
|
||||
output is printed on console.
|
@ -13,11 +13,10 @@
|
||||
all copies or substantial portions of the Software.
|
||||
*/
|
||||
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include <catch.hpp>
|
||||
#include <sys/time.h>
|
||||
#include "Arduino.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
extern "C" unsigned long millis()
|
||||
{
|
||||
@ -26,11 +25,22 @@ extern "C" unsigned long millis()
|
||||
return (time.tv_sec * 1000) + (time.tv_usec / 1000);
|
||||
}
|
||||
|
||||
extern "C" unsigned long micros()
|
||||
{
|
||||
timeval time;
|
||||
gettimeofday(&time, NULL);
|
||||
return (time.tv_sec * 1000000) + time.tv_usec;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void yield()
|
||||
{
|
||||
}
|
||||
|
||||
extern "C" void esp_yield()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
extern "C" void __panic_func(const char* file, int line, const char* func) {
|
||||
abort();
|
||||
@ -38,4 +48,10 @@ extern "C" void __panic_func(const char* file, int line, const char* func) {
|
||||
|
||||
extern "C" void delay(unsigned long ms)
|
||||
{
|
||||
usleep(ms * 1000);
|
||||
}
|
||||
|
||||
extern "C" void delayMicroseconds(unsigned int us)
|
||||
{
|
||||
usleep(us);
|
||||
}
|
||||
|
@ -20,6 +20,8 @@
|
||||
#ifndef Arduino_h
|
||||
#define Arduino_h
|
||||
|
||||
#define MOCK "mock: "
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
20
tests/host/common/ArduinoCatch.cpp
Normal file
20
tests/host/common/ArduinoCatch.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
Arduino.cpp - Mocks for common Arduino APIs
|
||||
Copyright © 2016 Ivan Grokhotkov
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in 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:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
*/
|
||||
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include <catch.hpp>
|
||||
#include <sys/time.h>
|
||||
#include "Arduino.h"
|
||||
|
143
tests/host/common/ArduinoMain.cpp
Normal file
143
tests/host/common/ArduinoMain.cpp
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
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 <Arduino.h>
|
||||
#include <user_interface.h> // wifi_get_ip_info()
|
||||
|
||||
#include <functional>
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/igmp.h"
|
||||
#include "lwip/mem.h"
|
||||
#include <include/UdpContext.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include <unistd.h> // usleep
|
||||
#include <getopt.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
#if 0
|
||||
#include "../common/spiffs_mock.h"
|
||||
#include <spiffs/spiffs.h>
|
||||
SPIFFS_MOCK_DECLARE(/*size_kb*/1024, /(blovk_kb*/8, /*page_b*/512);
|
||||
#endif
|
||||
|
||||
std::map<int,UdpContext*> udps;
|
||||
|
||||
void register_udp (int sock, UdpContext* udp)
|
||||
{
|
||||
if (udp)
|
||||
udps[sock] = udp;
|
||||
else
|
||||
udps.erase(sock);
|
||||
}
|
||||
|
||||
const char* host_interface = nullptr;
|
||||
|
||||
void help (const char* argv0, int exitcode)
|
||||
{
|
||||
printf(
|
||||
"%s - compiled with esp8266/arduino emulator\n"
|
||||
"options:\n"
|
||||
" -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"
|
||||
" -f - no throttle (possibly 100%%CPU)\n"
|
||||
, argv0);
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
static struct option options[] =
|
||||
{
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "fast", no_argument, NULL, 'f' },
|
||||
{ "local", no_argument, NULL, 'l' },
|
||||
{ "interface", required_argument, NULL, 'i' },
|
||||
};
|
||||
|
||||
int main (int argc, char* const argv [])
|
||||
{
|
||||
bool fast = false;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int n = getopt_long(argc, argv, "hlfi:", options, NULL);
|
||||
if (n < 0)
|
||||
break;
|
||||
switch (n)
|
||||
{
|
||||
case 'h':
|
||||
help(argv[0], EXIT_SUCCESS);
|
||||
break;
|
||||
case 'i':
|
||||
host_interface = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
global_ipv4_netfmt = NO_GLOBAL_BINDING;
|
||||
break;
|
||||
case 'f':
|
||||
fast = true;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, MOCK "bad option '%c'\n", n);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
// setup global global_ipv4_netfmt
|
||||
wifi_get_ip_info(0, nullptr);
|
||||
|
||||
setup();
|
||||
while (true)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
151
tests/host/common/ClientContextSocket.cpp
Normal file
151
tests/host/common/ClientContextSocket.cpp
Normal file
@ -0,0 +1,151 @@
|
||||
|
||||
/*
|
||||
Arduino emulation - socket part of ClientContext
|
||||
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.
|
||||
*/
|
||||
// separated from lwIP to avoid type conflicts
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <poll.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
int mockConnect (uint32_t ipv4, int& sock, int port)
|
||||
{
|
||||
struct sockaddr_in server;
|
||||
if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||
{
|
||||
perror(MOCK "ClientContext:connect: ::socket()");
|
||||
return 0;
|
||||
}
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(port);
|
||||
memcpy(&server.sin_addr, &ipv4, 4);
|
||||
if (::connect(sock, (struct sockaddr*)&server, sizeof(server)) == -1)
|
||||
{
|
||||
perror(MOCK "ClientContext::connect: ::connect()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
|
||||
{
|
||||
fprintf(stderr, MOCK "ClientContext::connect: fcntl(O_NONBLOCK): %s\n", strerror(errno));
|
||||
close(sock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_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));
|
||||
ret = 0;
|
||||
}
|
||||
return ccinbufsize += ret;
|
||||
}
|
||||
|
||||
size_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);
|
||||
|
||||
struct pollfd p;
|
||||
size_t retsize = 0;
|
||||
do
|
||||
{
|
||||
if (usersize <= ccinbufsize)
|
||||
{
|
||||
// data already buffered
|
||||
retsize = usersize;
|
||||
break;
|
||||
}
|
||||
|
||||
// check incoming data data
|
||||
mockFillInBuf(sock, ccinbuf, ccinbufsize);
|
||||
if (usersize <= ccinbufsize)
|
||||
{
|
||||
// data just received
|
||||
retsize = usersize;
|
||||
break;
|
||||
}
|
||||
|
||||
// wait for more data until timeout
|
||||
p.fd = sock;
|
||||
p.events = POLLIN;
|
||||
} while (poll(&p, 1, timeout_ms) == 1);
|
||||
|
||||
memcpy(dst, ccinbuf, retsize);
|
||||
return retsize;
|
||||
}
|
||||
|
||||
size_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);
|
||||
// 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)
|
||||
{
|
||||
struct pollfd p;
|
||||
p.fd = sock;
|
||||
p.events = POLLOUT;
|
||||
int ret = poll(&p, 1, timeout_ms);
|
||||
if (ret == -1)
|
||||
{
|
||||
fprintf(stderr, MOCK "ClientContext::write: poll(%d): %s\n", sock, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
ret = ::write(sock, data, size);
|
||||
if (ret == -1)
|
||||
{
|
||||
fprintf(stderr, MOCK "ClientContext::read: write(%d): %s\n", sock, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if (ret != (int)size)
|
||||
{
|
||||
fprintf(stderr, MOCK "ClientContext::write: short write (%d < %zd) (TODO)\n", ret, size);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
57
tests/host/common/ClientContextTools.cpp
Normal file
57
tests/host/common/ClientContextTools.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
Arduino emulation - part of ClientContext
|
||||
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/def.h>
|
||||
#include <lwip/tcp.h>
|
||||
#include <lwip/dns.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <include/ClientContext.h>
|
||||
|
||||
#include <netdb.h> // gethostbyname
|
||||
|
||||
err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg)
|
||||
{
|
||||
(void)callback_arg;
|
||||
(void)found;
|
||||
struct hostent* hbn = gethostbyname(hostname);
|
||||
if (!hbn)
|
||||
return ERR_TIMEOUT;
|
||||
addr->addr = *(uint32_t*)hbn->h_addr_list[0];
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static struct tcp_pcb mock_tcp_pcb;
|
||||
tcp_pcb* tcp_new (void)
|
||||
{
|
||||
// this is useless
|
||||
// ClientContext is setting the source port and we don't care here
|
||||
return &mock_tcp_pcb;
|
||||
}
|
81
tests/host/common/EEPROM.h
Normal file
81
tests/host/common/EEPROM.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
Arduino EEPROM emulation
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef EEPROM_MOCK
|
||||
#define EEPROM_MOCK
|
||||
|
||||
class EEPROMClass {
|
||||
public:
|
||||
EEPROMClass(uint32_t sector);
|
||||
EEPROMClass(void);
|
||||
~EEPROMClass();
|
||||
|
||||
void begin(size_t size);
|
||||
uint8_t read(int address);
|
||||
void write(int address, uint8_t val);
|
||||
bool commit();
|
||||
void end();
|
||||
|
||||
template<typename T>
|
||||
T& get(int const address, T& t)
|
||||
{
|
||||
if (address < 0 || address + sizeof(T) > _size)
|
||||
return t;
|
||||
for (size_t i = 0; i < sizeof(T); i++)
|
||||
((uint8_t*)&t)[i] = read(i);
|
||||
return t;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T& put(int const address, const T& t)
|
||||
{
|
||||
if (address < 0 || address + sizeof(T) > _size)
|
||||
return t;
|
||||
for (size_t i = 0; i < sizeof(T); i++)
|
||||
write(i, ((uint8_t*)&t)[i]);
|
||||
return t;
|
||||
}
|
||||
|
||||
size_t length() { return _size; }
|
||||
|
||||
//uint8_t& operator[](int const address) { return read(address); }
|
||||
uint8_t operator[] (int address) { return read(address); }
|
||||
|
||||
protected:
|
||||
size_t _size = 0;
|
||||
int _fd = -1;
|
||||
};
|
||||
|
||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_EEPROM)
|
||||
extern EEPROMClass EEPROM;
|
||||
#endif
|
||||
|
||||
#endif
|
71
tests/host/common/HostWiring.cpp
Normal file
71
tests/host/common/HostWiring.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
Arduino: wire emulation
|
||||
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 <Arduino.h>
|
||||
|
||||
void pinMode (uint8_t pin, uint8_t mode)
|
||||
{
|
||||
#define xxx(mode) case mode: m=STRHELPER(mode); break
|
||||
const char* m;
|
||||
switch (mode)
|
||||
{
|
||||
case INPUT: m="INPUT"; break;
|
||||
case OUTPUT: m="OUTPUT"; break;
|
||||
case INPUT_PULLUP: m="INPUT_PULLUP"; break;
|
||||
case OUTPUT_OPEN_DRAIN: m="OUTPUT_OPEN_DRAIN"; break;
|
||||
case INPUT_PULLDOWN_16: m="INPUT_PULLDOWN_16"; break;
|
||||
case WAKEUP_PULLUP: m="WAKEUP_PULLUP"; break;
|
||||
case WAKEUP_PULLDOWN: m="WAKEUP_PULLDOWN"; break;
|
||||
default: m="(special)";
|
||||
}
|
||||
fprintf(stderr, MOCK "gpio%d: mode='%s'\n", pin, m);
|
||||
}
|
||||
|
||||
void digitalWrite(uint8_t pin, uint8_t val)
|
||||
{
|
||||
fprintf(stderr, MOCK "digitalWrite(pin=%d val=%d)\n", pin, val);
|
||||
}
|
||||
|
||||
void analogWrite(uint8_t pin, int val)
|
||||
{
|
||||
fprintf(stderr, MOCK "analogWrite(pin=%d, val=%d\n", pin, val);
|
||||
}
|
||||
|
||||
int analogRead(uint8_t pin)
|
||||
{
|
||||
(void)pin;
|
||||
return 512;
|
||||
}
|
||||
|
||||
void analogWriteRange(uint32_t range)
|
||||
{
|
||||
fprintf(stderr, MOCK "analogWriteRange(range=%d)\n", range);
|
||||
}
|
97
tests/host/common/MockEEPROM.cpp
Normal file
97
tests/host/common/MockEEPROM.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
Arduino emulation - EEPROM
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __EEPROM_H
|
||||
#define __EEPROM_H
|
||||
|
||||
#include <EEPROM.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define EEPROM_FILE_NAME "eeprom"
|
||||
|
||||
EEPROMClass::EEPROMClass ()
|
||||
{
|
||||
}
|
||||
|
||||
EEPROMClass::~EEPROMClass ()
|
||||
{
|
||||
if (_fd >= 0)
|
||||
close(_fd);
|
||||
}
|
||||
|
||||
void EEPROMClass::begin(size_t size)
|
||||
{
|
||||
_size = size;
|
||||
if ( (_fd = open(EEPROM_FILE_NAME, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1
|
||||
|| ftruncate(_fd, size) == -1)
|
||||
{
|
||||
fprintf(stderr, MOCK "EEPROM: cannot open/create '%s' for r/w: %s\n\r", EEPROM_FILE_NAME, strerror(errno));
|
||||
_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void EEPROMClass::end()
|
||||
{
|
||||
if (_fd != -1)
|
||||
close(_fd);
|
||||
}
|
||||
|
||||
bool EEPROMClass::commit()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t EEPROMClass::read (int x)
|
||||
{
|
||||
char c = 0;
|
||||
if (pread(_fd, &c, 1, x) != 1)
|
||||
fprintf(stderr, MOCK "eeprom: %s\n\r", strerror(errno));
|
||||
return c;
|
||||
}
|
||||
|
||||
void EEPROMClass::write (int x, uint8_t c)
|
||||
{
|
||||
if (x > (int)_size)
|
||||
fprintf(stderr, MOCK "### eeprom beyond\r\n");
|
||||
else if (pwrite(_fd, &c, 1, x) != 1)
|
||||
fprintf(stderr, MOCK "eeprom: %s\n\r", strerror(errno));
|
||||
}
|
||||
|
||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_EEPROM)
|
||||
EEPROMClass EEPROM;
|
||||
#endif
|
||||
|
||||
#endif
|
183
tests/host/common/MockEsp.cpp
Normal file
183
tests/host/common/MockEsp.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
Arduino emulation - esp8266's core
|
||||
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 <Esp.h>
|
||||
#include <eboot_command.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
unsigned long long operator"" _kHz(unsigned long long x) {
|
||||
return x * 1000;
|
||||
}
|
||||
|
||||
unsigned long long operator"" _MHz(unsigned long long x) {
|
||||
return x * 1000 * 1000;
|
||||
}
|
||||
|
||||
unsigned long long operator"" _GHz(unsigned long long x) {
|
||||
return x * 1000 * 1000 * 1000;
|
||||
}
|
||||
|
||||
unsigned long long operator"" _kBit(unsigned long long x) {
|
||||
return x * 1024;
|
||||
}
|
||||
|
||||
unsigned long long operator"" _MBit(unsigned long long x) {
|
||||
return x * 1024 * 1024;
|
||||
}
|
||||
|
||||
unsigned long long operator"" _GBit(unsigned long long x) {
|
||||
return x * 1024 * 1024 * 1024;
|
||||
}
|
||||
|
||||
unsigned long long operator"" _kB(unsigned long long x) {
|
||||
return x * 1024;
|
||||
}
|
||||
|
||||
unsigned long long operator"" _MB(unsigned long long x) {
|
||||
return x * 1024 * 1024;
|
||||
}
|
||||
|
||||
unsigned long long operator"" _GB(unsigned long long x) {
|
||||
return x * 1024 * 1024 * 1024;
|
||||
}
|
||||
|
||||
uint32_t _SPIFFS_start;
|
||||
|
||||
void eboot_command_write (struct eboot_command* cmd)
|
||||
{
|
||||
(void)cmd;
|
||||
}
|
||||
|
||||
EspClass ESP;
|
||||
|
||||
void EspClass::restart ()
|
||||
{
|
||||
fprintf(stderr, MOCK "Esp.restart(): exiting\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
uint32_t EspClass::getChipId()
|
||||
{
|
||||
return 0xee1337;
|
||||
}
|
||||
|
||||
bool EspClass::checkFlashConfig(bool needsEquals)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t EspClass::getSketchSize()
|
||||
{
|
||||
return 400000;
|
||||
}
|
||||
|
||||
uint32_t EspClass::getFreeHeap()
|
||||
{
|
||||
return 30000;
|
||||
}
|
||||
|
||||
bool EspClass::flashEraseSector(uint32_t sector)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
FlashMode_t EspClass::getFlashChipMode()
|
||||
{
|
||||
return FM_DOUT;
|
||||
}
|
||||
|
||||
FlashMode_t EspClass::magicFlashChipMode(uint8_t byte)
|
||||
{
|
||||
return FM_DOUT;
|
||||
}
|
||||
|
||||
bool EspClass::flashWrite(uint32_t offset, uint32_t *data, size_t size)
|
||||
{
|
||||
(void)offset;
|
||||
(void)data;
|
||||
(void)size;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EspClass::flashRead(uint32_t offset, uint32_t *data, size_t size)
|
||||
{
|
||||
(void)offset;
|
||||
(void)data;
|
||||
(void)size;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t EspClass::magicFlashChipSize(uint8_t byte) {
|
||||
switch(byte & 0x0F) {
|
||||
case 0x0: // 4 Mbit (512KB)
|
||||
return (512_kB);
|
||||
case 0x1: // 2 MBit (256KB)
|
||||
return (256_kB);
|
||||
case 0x2: // 8 MBit (1MB)
|
||||
return (1_MB);
|
||||
case 0x3: // 16 MBit (2MB)
|
||||
return (2_MB);
|
||||
case 0x4: // 32 MBit (4MB)
|
||||
return (4_MB);
|
||||
case 0x8: // 64 MBit (8MB)
|
||||
return (8_MB);
|
||||
case 0x9: // 128 MBit (16MB)
|
||||
return (16_MB);
|
||||
default: // fail?
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t EspClass::getFlashChipRealSize(void)
|
||||
{
|
||||
return magicFlashChipSize(4);
|
||||
}
|
||||
|
||||
uint32_t EspClass::getFlashChipSize(void)
|
||||
{
|
||||
return magicFlashChipSize(4);
|
||||
}
|
||||
|
||||
String EspClass::getFullVersion ()
|
||||
{
|
||||
return "host-emulation";
|
||||
}
|
||||
|
||||
uint32_t EspClass::getFreeContStack()
|
||||
{
|
||||
return 4000;
|
||||
}
|
||||
|
||||
void EspClass::resetFreeContStack()
|
||||
{
|
||||
}
|
||||
|
63
tests/host/common/MockSPI.cpp
Normal file
63
tests/host/common/MockSPI.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
Arduino emulation - spi
|
||||
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 <SPI.h>
|
||||
|
||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SPI)
|
||||
SPIClass SPI;
|
||||
#endif
|
||||
|
||||
SPIClass::SPIClass ()
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t SPIClass::transfer(uint8_t data)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
void SPIClass::begin()
|
||||
{
|
||||
}
|
||||
|
||||
void SPIClass::end()
|
||||
{
|
||||
}
|
||||
|
||||
void SPIClass::setFrequency(uint32_t freq)
|
||||
{
|
||||
(void)freq;
|
||||
}
|
||||
|
||||
void SPIClass::setHwCs(bool use)
|
||||
{
|
||||
(void)use;
|
||||
}
|
112
tests/host/common/MockSerial.cpp
Normal file
112
tests/host/common/MockSerial.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
Arduino Hardware Serial emulation
|
||||
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 <Arduino.h>
|
||||
|
||||
#include <unistd.h> // write
|
||||
|
||||
HardwareSerial Serial(UART0);
|
||||
|
||||
HardwareSerial::HardwareSerial (int uart_nr)
|
||||
{
|
||||
if (uart_nr != 0)
|
||||
fprintf(stderr, MOCK "FIXME HardwareSerial::HardwareSerial(%d)\n", uart_nr);
|
||||
}
|
||||
|
||||
void HardwareSerial::begin (unsigned long baud, SerialConfig config, SerialMode mode, uint8_t tx_pin)
|
||||
{
|
||||
if (config != SERIAL_8N1 || mode != SERIAL_FULL || tx_pin != 1)
|
||||
fprintf(stderr, MOCK "FIXME HardwareSerial::begin(baud=%ld config=0x%x mode=0x%x)\n", baud, (int)config, (int)mode);
|
||||
}
|
||||
|
||||
void HardwareSerial::setDebugOutput (bool on)
|
||||
{
|
||||
(void)on;
|
||||
}
|
||||
|
||||
int HardwareSerial::available (void)
|
||||
{
|
||||
printf(MOCK "TODO HardwareSerial::available\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HardwareSerial::flush ()
|
||||
{
|
||||
//XXXTODO
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
// uart.c
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
size_t uart_write_char (uart_t* uart, char c)
|
||||
{
|
||||
//XXXTODO
|
||||
(void)uart;
|
||||
return write(1, &c, 1);
|
||||
}
|
||||
|
||||
int uart_peek_char (uart_t* uart)
|
||||
{
|
||||
///XXXTODO
|
||||
static bool notimpl = false;
|
||||
if (!notimpl)
|
||||
{
|
||||
notimpl = true;
|
||||
fprintf(stderr, MOCK "FIXME uart_peek_char\n");
|
||||
}
|
||||
(void)uart;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int uart_read_char (uart_t* uart)
|
||||
{
|
||||
///XXXTODO
|
||||
static bool notimpl = false;
|
||||
if (!notimpl)
|
||||
{
|
||||
notimpl = true;
|
||||
fprintf(stderr, MOCK "FIXME uart_read_char\n");
|
||||
}
|
||||
(void)uart;
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t uart_write (uart_t* uart, const char* buf, size_t size)
|
||||
{
|
||||
///XXXTODO
|
||||
(void)uart;
|
||||
return write(1, buf, size);
|
||||
}
|
||||
|
||||
} // extern "C"
|
79
tests/host/common/MockTools.cpp
Normal file
79
tests/host/common/MockTools.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
Arduino emulation - tools
|
||||
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 <arpa/inet.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
uint32_t lwip_htonl (uint32_t hostlong) { return htonl(hostlong); }
|
||||
uint16_t lwip_htons (uint16_t hostshort) { return htons(hostshort); }
|
||||
uint32_t lwip_ntohl (uint32_t netlong) { return ntohl(netlong); }
|
||||
uint16_t lwip_ntohs (uint16_t netshort) { return ntohs(netshort); }
|
||||
|
||||
char* ets_strcpy (char* d, const char* s) { return strcpy(d, s); }
|
||||
size_t ets_strlen (const char* s) { return strlen(s); }
|
||||
|
||||
int ets_printf (const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
int len = vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
return len;
|
||||
}
|
||||
|
||||
extern "C" void configTime(long timezone, int daylightOffset_sec,
|
||||
const char* server1, const char* server2, const char* server3)
|
||||
{
|
||||
(void)server1;
|
||||
(void)server2;
|
||||
(void)server3;
|
||||
|
||||
fprintf(stderr, MOCK "configTime: TODO (tz=%ldH offset=%dS) (time will be host's)\n", timezone, daylightOffset_sec);
|
||||
}
|
||||
|
||||
void stack_thunk_add_ref() { }
|
||||
void stack_thunk_del_ref() { }
|
||||
void stack_thunk_repaint() { }
|
||||
|
||||
uint32_t stack_thunk_get_refcnt() { return 0; }
|
||||
uint32_t stack_thunk_get_stack_top() { return 0; }
|
||||
uint32_t stack_thunk_get_stack_bot() { return 0; }
|
||||
uint32_t stack_thunk_get_cont_sp() { return 0; }
|
||||
uint32_t stack_thunk_get_max_usage() { return 0; }
|
||||
void stack_thunk_dump_stack() { }
|
||||
|
||||
// Thunking macro
|
||||
#define make_stack_thunk(fcnToThunk)
|
||||
|
||||
};
|
82
tests/host/common/MockWiFiServer.cpp
Normal file
82
tests/host/common/MockWiFiServer.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
Arduino emulation - WiFiServer
|
||||
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 <WiFiClient.h>
|
||||
#include <WiFiServer.h>
|
||||
|
||||
#include <lwip/err.h>
|
||||
#include <lwip/ip_addr.h>
|
||||
|
||||
#include <include/ClientContext.h>
|
||||
|
||||
extern "C" const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY);
|
||||
|
||||
#define int2pcb(x) ((tcp_pcb*)(intptr_t)(x))
|
||||
#define pcb2int(x) ((int)(intptr_t)(x))
|
||||
|
||||
// lwIP API side of WiFiServer
|
||||
|
||||
WiFiServer::WiFiServer (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;
|
||||
}
|
||||
|
||||
WiFiClient WiFiServer::available (uint8_t* status)
|
||||
{
|
||||
(void)status;
|
||||
if (hasClient())
|
||||
return WiFiClient(new ClientContext(serverAccept(pcb2int(_pcb))));
|
||||
return WiFiClient();
|
||||
}
|
||||
|
||||
// static declaration
|
||||
|
||||
#include <include/UdpContext.h>
|
||||
uint32_t UdpContext::staticMCastAddr = 0;
|
||||
|
127
tests/host/common/MockWiFiServerSocket.cpp
Normal file
127
tests/host/common/MockWiFiServerSocket.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
Arduino emulation - WiFiServer socket side
|
||||
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 <WiFiServer.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define int2pcb(x) ((tcp_pcb*)(intptr_t)(x))
|
||||
#define pcb2int(x) ((int)(intptr_t)(x))
|
||||
|
||||
// host socket internal side of WiFiServer
|
||||
|
||||
int serverAccept (int srvsock)
|
||||
{
|
||||
int clisock;
|
||||
socklen_t n;
|
||||
struct sockaddr_in client;
|
||||
n = sizeof(client);
|
||||
if ((clisock = accept(srvsock, (struct sockaddr*)&client, &n)) == -1)
|
||||
{
|
||||
perror("accept()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return clisock;
|
||||
}
|
||||
|
||||
void WiFiServer::begin (uint16_t port)
|
||||
{
|
||||
_port = port;
|
||||
return begin();
|
||||
}
|
||||
|
||||
void WiFiServer::begin ()
|
||||
{
|
||||
int sock;
|
||||
struct sockaddr_in server;
|
||||
|
||||
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||
{
|
||||
perror(MOCK "socket()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int optval = 1;
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)) == -1)
|
||||
{
|
||||
perror(MOCK "reuseport");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(_port);
|
||||
server.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
if (bind(sock, (struct sockaddr*)&server, sizeof(server)) == -1)
|
||||
{
|
||||
perror(MOCK "bind()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (listen(sock, 1) == -1)
|
||||
{
|
||||
perror(MOCK "listen()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
// store int into pointer
|
||||
_pcb = int2pcb(sock);
|
||||
}
|
||||
|
||||
bool WiFiServer::hasClient ()
|
||||
{
|
||||
struct pollfd p;
|
||||
p.fd = pcb2int(_pcb);
|
||||
p.events = POLLIN;
|
||||
return poll(&p, 1, 0) && p.revents == POLLIN;
|
||||
}
|
||||
|
||||
size_t WiFiServer::write (uint8_t c)
|
||||
{
|
||||
return write(&c, 1);
|
||||
}
|
||||
|
||||
size_t WiFiServer::write (const uint8_t *buf, size_t size)
|
||||
{
|
||||
fprintf(stderr, MOCK "todo: WiFiServer::write(%p, %zd)\n", buf, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WiFiServer::close ()
|
||||
{
|
||||
if (pcb2int(_pcb) >= 0)
|
||||
::close(pcb2int(_pcb));
|
||||
_pcb = int2pcb(-1);
|
||||
}
|
182
tests/host/common/UdpContextSocket.cpp
Normal file
182
tests/host/common/UdpContextSocket.cpp
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
Arduino emulation - UdpContext emulation - socket part
|
||||
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 <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <poll.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
int mockUDPSocket ()
|
||||
{
|
||||
int s;
|
||||
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1 || fcntl(s, F_SETFL, O_NONBLOCK) == -1)
|
||||
{
|
||||
fprintf(stderr, MOCK "UDP socket: %s", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast)
|
||||
{
|
||||
int optval = 1;
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)) == -1)
|
||||
fprintf(stderr, MOCK "SO_REUSEPORT failed\n");
|
||||
optval = 1;
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1)
|
||||
fprintf(stderr, MOCK "SO_REUSEADDR failed\n");
|
||||
|
||||
struct sockaddr_in servaddr;
|
||||
memset(&servaddr, 0, sizeof(servaddr));
|
||||
|
||||
// Filling server information
|
||||
servaddr.sin_family = AF_INET;
|
||||
//servaddr.sin_addr.s_addr = global_ipv4_netfmt?: dstaddr;
|
||||
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
servaddr.sin_port = htons(port);
|
||||
|
||||
// Bind the socket with the server address
|
||||
if (bind(sock, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
|
||||
{
|
||||
fprintf(stderr, MOCK "UDP bind on port %d failed: %s\n", port, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
fprintf(stderr, MOCK "UDP server on port %d (sock=%d)\n", (int)port, sock);
|
||||
|
||||
if (mcast)
|
||||
{
|
||||
// https://web.cs.wpi.edu/~claypool/courses/4514-B99/samples/multicast.c
|
||||
// https://stackoverflow.com/questions/12681097/c-choose-interface-for-udp-multicast-socket
|
||||
|
||||
struct ip_mreq mreq;
|
||||
mreq.imr_multiaddr.s_addr = mcast;
|
||||
//mreq.imr_interface.s_addr = global_ipv4_netfmt?: htonl(INADDR_ANY);
|
||||
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
||||
if (global_ipv4_netfmt)
|
||||
{
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, host_interface, strlen(host_interface)) == -1)
|
||||
fprintf(stderr, MOCK "UDP multicast: can't setup bind/output on interface %s: %s\n", host_interface, strerror(errno));
|
||||
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &mreq.imr_interface, sizeof(struct in_addr)) == -1)
|
||||
fprintf(stderr, MOCK "UDP multicast: can't setup bind/input on interface %s: %s\n", host_interface, strerror(errno));
|
||||
}
|
||||
|
||||
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||
{
|
||||
fprintf(stderr, MOCK "can't join multicast group addr %08x\n", (int)mcast);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
size_t mockUDPFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize, uint8_t& addrsize, uint8_t addr[16], uint16_t& port)
|
||||
{
|
||||
struct sockaddr_storage addrbuf;
|
||||
socklen_t addrbufsize = std::min((socklen_t)sizeof(addrbuf), (socklen_t)16);
|
||||
|
||||
size_t maxread = CCBUFSIZE - ccinbufsize;
|
||||
ssize_t ret = ::recvfrom(sock, ccinbuf + ccinbufsize, maxread, 0/*flags*/, (sockaddr*)&addrbuf, &addrbufsize);
|
||||
if (ret == -1)
|
||||
{
|
||||
if (errno != EAGAIN)
|
||||
fprintf(stderr, MOCK "UDPContext::(read/peek): filling buffer for %zd bytes: %s\n", maxread, strerror(errno));
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (ret > 0)
|
||||
{
|
||||
port = ntohs(((sockaddr_in*)&addrbuf)->sin_port);
|
||||
if (addrbuf.ss_family == AF_INET)
|
||||
memcpy(&addr[0], &(((sockaddr_in*)&addrbuf)->sin_addr.s_addr), addrsize = 4);
|
||||
else
|
||||
{
|
||||
fprintf(stderr, MOCK "TODO UDP+IPv6\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
return ccinbufsize += ret;
|
||||
}
|
||||
|
||||
size_t mockUDPPeekBytes (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);
|
||||
|
||||
size_t retsize = 0;
|
||||
if (ccinbufsize)
|
||||
{
|
||||
// data already buffered
|
||||
retsize = usersize;
|
||||
if (retsize > ccinbufsize)
|
||||
retsize = ccinbufsize;
|
||||
}
|
||||
memcpy(dst, ccinbuf, retsize);
|
||||
return retsize;
|
||||
}
|
||||
|
||||
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);
|
||||
// swallow (XXX use a circular buffer?)
|
||||
memmove(ccinbuf, ccinbuf + copied, ccinbufsize - copied);
|
||||
ccinbufsize -= copied;
|
||||
return copied;
|
||||
}
|
||||
|
||||
size_t mockUDPWrite (int sock, const uint8_t* data, size_t size, int timeout_ms, uint32_t ipv4, uint16_t port)
|
||||
{
|
||||
// Filling server information
|
||||
struct sockaddr_in peer;
|
||||
peer.sin_family = AF_INET;
|
||||
peer.sin_addr.s_addr = ipv4; //XXFIXME should use lwip_htonl?
|
||||
peer.sin_port = htons(port);
|
||||
int ret = ::sendto(sock, data, size, 0/*flags*/, (const sockaddr*)&peer, sizeof(peer));
|
||||
if (ret == -1)
|
||||
{
|
||||
fprintf(stderr, MOCK "UDPContext::write: write(%d): %s\n", sock, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if (ret != (int)size)
|
||||
{
|
||||
fprintf(stderr, MOCK "UDPContext::write: short write (%d < %zd) (TODO)\n", ret, size);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
@ -25,6 +25,7 @@
|
||||
|
||||
extern "C" {
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
}
|
||||
|
||||
void randomSeed(unsigned long seed) {
|
||||
@ -52,10 +53,10 @@ long map(long x, long in_min, long in_max, long out_min, long out_max) {
|
||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
}
|
||||
|
||||
unsigned int makeWord(unsigned int w) {
|
||||
uint16_t makeWord(unsigned int w) {
|
||||
return w;
|
||||
}
|
||||
|
||||
unsigned int makeWord(unsigned char h, unsigned char l) {
|
||||
uint16_t makeWord(unsigned char h, unsigned char l) {
|
||||
return (h << 8) | l;
|
||||
}
|
||||
|
115
tests/host/common/c_types.h
Normal file
115
tests/host/common/c_types.h
Normal file
@ -0,0 +1,115 @@
|
||||
|
||||
// This is a copy of SDK's "c_type.h"
|
||||
// with conflicting declarations commented out
|
||||
// (search CONFLICT in this file)
|
||||
|
||||
// diff -u common/c_types.h ../../tools/sdk/include/c_types.h
|
||||
|
||||
/*
|
||||
* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2016 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case,
|
||||
* it is free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in 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:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* 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 AUTHORS 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 IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _C_TYPES_H_
|
||||
#define _C_TYPES_H_
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
typedef signed char sint8_t;
|
||||
typedef signed short sint16_t;
|
||||
typedef signed long sint32_t;
|
||||
typedef signed long long sint64_t;
|
||||
// CONFLICT typedef unsigned long long u_int64_t;
|
||||
typedef float real32_t;
|
||||
typedef double real64_t;
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned char u8;
|
||||
typedef signed char sint8;
|
||||
typedef signed char int8;
|
||||
typedef signed char s8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned short u16;
|
||||
typedef signed short sint16;
|
||||
typedef signed short s16;
|
||||
typedef unsigned int uint32;
|
||||
typedef unsigned int u_int;
|
||||
typedef unsigned int u32;
|
||||
typedef signed int sint32;
|
||||
typedef signed int s32;
|
||||
typedef int int32;
|
||||
typedef signed long long sint64;
|
||||
typedef unsigned long long uint64;
|
||||
typedef unsigned long long u64;
|
||||
typedef float real32;
|
||||
typedef double real64;
|
||||
|
||||
#define __le16 u16
|
||||
|
||||
#define LOCAL static
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL (void *)0
|
||||
#endif /* NULL */
|
||||
|
||||
/* probably should not put STATUS here */
|
||||
typedef enum {
|
||||
OK = 0,
|
||||
FAIL,
|
||||
PENDING,
|
||||
BUSY,
|
||||
CANCEL,
|
||||
} STATUS;
|
||||
|
||||
#define BIT(nr) (1UL << (nr))
|
||||
|
||||
#define REG_SET_BIT(_r, _b) (*(volatile uint32_t*)(_r) |= (_b))
|
||||
#define REG_CLR_BIT(_r, _b) (*(volatile uint32_t*)(_r) &= ~(_b))
|
||||
|
||||
#define DMEM_ATTR __attribute__((section(".bss")))
|
||||
#define SHMEM_ATTR
|
||||
|
||||
#ifdef ICACHE_FLASH
|
||||
#define __ICACHE_STRINGIZE_NX(A) #A
|
||||
#define __ICACHE_STRINGIZE(A) __ICACHE_STRINGIZE_NX(A)
|
||||
#define ICACHE_FLASH_ATTR __attribute__((section("\".irom0.text." __FILE__ "." __ICACHE_STRINGIZE(__LINE__) "." __ICACHE_STRINGIZE(__COUNTER__) "\"")))
|
||||
#define ICACHE_RAM_ATTR __attribute__((section("\".iram.text." __FILE__ "." __ICACHE_STRINGIZE(__LINE__) "." __ICACHE_STRINGIZE(__COUNTER__) "\"")))
|
||||
#define ICACHE_RODATA_ATTR __attribute__((section("\".irom.text." __FILE__ "." __ICACHE_STRINGIZE(__LINE__) "." __ICACHE_STRINGIZE(__COUNTER__) "\"")))
|
||||
#else
|
||||
#define ICACHE_FLASH_ATTR
|
||||
#define ICACHE_RAM_ATTR
|
||||
#define ICACHE_RODATA_ATTR
|
||||
#endif /* ICACHE_FLASH */
|
||||
|
||||
#define STORE_ATTR __attribute__((aligned(4)))
|
||||
|
||||
#ifndef __cplusplus
|
||||
#define BOOL bool
|
||||
#define TRUE true
|
||||
#define FALSE false
|
||||
|
||||
|
||||
#endif /* !__cplusplus */
|
||||
|
||||
#endif /* _C_TYPES_H_ */
|
7
tests/host/common/esp8266_peri.h
Normal file
7
tests/host/common/esp8266_peri.h
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
#ifndef FAKE_ESP8266_PERI_H
|
||||
#define FAKE_ESP8266_PERI_H
|
||||
|
||||
const int GPI = 0;
|
||||
|
||||
#endif
|
286
tests/host/common/include/ClientContext.h
Normal file
286
tests/host/common/include/ClientContext.h
Normal file
@ -0,0 +1,286 @@
|
||||
/*
|
||||
ClientContext.h - emulation of TCP connection handling on top of lwIP
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef CLIENTCONTEXT_H
|
||||
#define CLIENTCONTEXT_H
|
||||
|
||||
class ClientContext;
|
||||
class WiFiClient;
|
||||
|
||||
extern "C" void esp_yield();
|
||||
extern "C" void esp_schedule();
|
||||
|
||||
#include <include/DataSource.h>
|
||||
|
||||
bool getDefaultPrivateGlobalSyncValue ();
|
||||
|
||||
typedef void (*discard_cb_t)(void*, ClientContext*);
|
||||
|
||||
class ClientContext
|
||||
{
|
||||
public:
|
||||
ClientContext(tcp_pcb* pcb, discard_cb_t discard_cb, void* discard_cb_arg) :
|
||||
_discard_cb(discard_cb), _discard_cb_arg(discard_cb_arg), _refcnt(0), _next(0),
|
||||
_sync(::getDefaultPrivateGlobalSyncValue()), _sock(-1)
|
||||
{
|
||||
(void)pcb;
|
||||
}
|
||||
|
||||
ClientContext (int sock) :
|
||||
_discard_cb(nullptr), _discard_cb_arg(nullptr), _refcnt(0), _next(nullptr),
|
||||
_sync(::getDefaultPrivateGlobalSyncValue()), _sock(sock)
|
||||
{
|
||||
}
|
||||
|
||||
err_t abort()
|
||||
{
|
||||
if (_sock >= 0)
|
||||
::close(_sock);
|
||||
_sock = -1;
|
||||
return ERR_ABRT;
|
||||
}
|
||||
|
||||
err_t close()
|
||||
{
|
||||
abort();
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
~ClientContext()
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
ClientContext* next() const
|
||||
{
|
||||
return _next;
|
||||
}
|
||||
|
||||
ClientContext* next(ClientContext* new_next)
|
||||
{
|
||||
_next = new_next;
|
||||
return _next;
|
||||
}
|
||||
|
||||
void ref()
|
||||
{
|
||||
++_refcnt;
|
||||
DEBUGV(":ref %d\r\n", _refcnt);
|
||||
}
|
||||
|
||||
void unref()
|
||||
{
|
||||
DEBUGV(":ur %d\r\n", _refcnt);
|
||||
if(--_refcnt == 0) {
|
||||
discard_received();
|
||||
close();
|
||||
if (_discard_cb)
|
||||
_discard_cb(_discard_cb_arg, this);
|
||||
DEBUGV(":del\r\n");
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
int connect(ip_addr_t* addr, uint16_t port)
|
||||
{
|
||||
return mockConnect(addr->addr, _sock, port);
|
||||
}
|
||||
|
||||
size_t availableForWrite()
|
||||
{
|
||||
// XXXFIXME be smarter
|
||||
return 512;
|
||||
}
|
||||
|
||||
void setNoDelay(bool nodelay)
|
||||
{
|
||||
fprintf(stderr, MOCK "TODO setNoDelay(%d)\n", (int)nodelay);
|
||||
}
|
||||
|
||||
bool getNoDelay() const
|
||||
{
|
||||
fprintf(stderr, MOCK "TODO getNoDelay()\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
void setTimeout(int timeout_ms)
|
||||
{
|
||||
_timeout_ms = timeout_ms;
|
||||
}
|
||||
|
||||
int getTimeout() const
|
||||
{
|
||||
return _timeout_ms;
|
||||
}
|
||||
|
||||
uint32_t getRemoteAddress() const
|
||||
{
|
||||
fprintf(stderr, MOCK "TODO getRemoteAddress()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t getRemotePort() const
|
||||
{
|
||||
fprintf(stderr, MOCK "TODO getRemotePort()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t getLocalAddress() const
|
||||
{
|
||||
fprintf(stderr, MOCK "TODO getLocalAddress()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t getLocalPort() const
|
||||
{
|
||||
fprintf(stderr, MOCK "TODO getLocalPort()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t getSize()
|
||||
{
|
||||
return _inbufsize?: mockFillInBuf(_sock, _inbuf, _inbufsize);
|
||||
}
|
||||
|
||||
int read()
|
||||
{
|
||||
char c;
|
||||
return read(&c, 1)? c: -1;
|
||||
}
|
||||
|
||||
size_t read (char* dst, size_t size)
|
||||
{
|
||||
return mockRead(_sock, dst, size, 0, _inbuf, _inbufsize);
|
||||
}
|
||||
|
||||
int peek()
|
||||
{
|
||||
char c;
|
||||
return peekBytes(&c, 1)? c: -1;
|
||||
}
|
||||
|
||||
size_t peekBytes(char *dst, size_t size)
|
||||
{
|
||||
return mockPeekBytes(_sock, dst, size, _timeout_ms, _inbuf, _inbufsize);
|
||||
}
|
||||
|
||||
void discard_received()
|
||||
{
|
||||
fprintf(stderr, MOCK "TODO: ClientContext::discard_received()\n");
|
||||
}
|
||||
|
||||
bool wait_until_sent(int max_wait_ms = WIFICLIENT_MAX_FLUSH_WAIT_MS)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t state() const
|
||||
{
|
||||
return _sock >= 0? ESTABLISHED: CLOSED;
|
||||
}
|
||||
|
||||
size_t write(const uint8_t* data, size_t size)
|
||||
{
|
||||
return mockWrite(_sock, data, size, _timeout_ms);
|
||||
}
|
||||
|
||||
size_t write(Stream& stream)
|
||||
{
|
||||
size_t avail = stream.available();
|
||||
uint8_t buf [avail];
|
||||
avail = stream.readBytes(buf, avail);
|
||||
size_t totwrote = 0;
|
||||
uint8_t* w = buf;
|
||||
while (avail)
|
||||
{
|
||||
size_t wrote = write(w, avail);
|
||||
w += wrote;
|
||||
avail -= wrote;
|
||||
totwrote += wrote;
|
||||
}
|
||||
return totwrote;
|
||||
}
|
||||
|
||||
size_t write_P(PGM_P buf, size_t size)
|
||||
{
|
||||
return write((const uint8_t*)buf, size);
|
||||
}
|
||||
|
||||
void keepAlive (uint16_t idle_sec = TCP_DEFAULT_KEEPALIVE_IDLE_SEC, uint16_t intv_sec = TCP_DEFAULT_KEEPALIVE_INTERVAL_SEC, uint8_t count = TCP_DEFAULT_KEEPALIVE_COUNT)
|
||||
{
|
||||
fprintf(stderr, MOCK "TODO ClientContext::keepAlive()\n");
|
||||
}
|
||||
|
||||
bool isKeepAliveEnabled () const
|
||||
{
|
||||
fprintf(stderr, MOCK "TODO ClientContext::isKeepAliveEnabled()\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t getKeepAliveIdle () const
|
||||
{
|
||||
fprintf(stderr, MOCK "TODO ClientContext::getKeepAliveIdle()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t getKeepAliveInterval () const
|
||||
{
|
||||
fprintf(stderr, MOCK "TODO ClientContext::getKeepAliveInternal()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t getKeepAliveCount () const
|
||||
{
|
||||
fprintf(stderr, MOCK "TODO ClientContext::getKeepAliveCount()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool getSync () const
|
||||
{
|
||||
fprintf(stderr, MOCK "TODO ClientContext::getSync()\n");
|
||||
return _sync;
|
||||
}
|
||||
|
||||
void setSync (bool sync)
|
||||
{
|
||||
fprintf(stderr, MOCK "TODO ClientContext::setSync()\n");
|
||||
_sync = sync;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
discard_cb_t _discard_cb = nullptr;
|
||||
void* _discard_cb_arg = nullptr;
|
||||
|
||||
int8_t _refcnt;
|
||||
ClientContext* _next;
|
||||
|
||||
bool _sync;
|
||||
|
||||
// MOCK
|
||||
|
||||
int _sock = -1;
|
||||
int _timeout_ms = 5000;
|
||||
|
||||
char _inbuf [CCBUFSIZE];
|
||||
size_t _inbufsize = 0;
|
||||
};
|
||||
|
||||
#endif //CLIENTCONTEXT_H
|
254
tests/host/common/include/UdpContext.h
Normal file
254
tests/host/common/include/UdpContext.h
Normal file
@ -0,0 +1,254 @@
|
||||
/*
|
||||
UdpContext.h - emulation of UDP connection handling on top of lwIP
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef UDPCONTEXT_H
|
||||
#define UDPCONTEXT_H
|
||||
|
||||
#include <functional>
|
||||
|
||||
class UdpContext;
|
||||
|
||||
#define GET_IP_HDR(pb) reinterpret_cast<ip_hdr*>(((uint8_t*)((pb)->payload)) - UDP_HLEN - IP_HLEN);
|
||||
#define GET_UDP_HDR(pb) reinterpret_cast<udp_hdr*>(((uint8_t*)((pb)->payload)) - UDP_HLEN);
|
||||
|
||||
class UdpContext
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::function<void(void)> rxhandler_t;
|
||||
|
||||
UdpContext(): _on_rx(nullptr), _refcnt(0)
|
||||
{
|
||||
_sock = mockUDPSocket();
|
||||
}
|
||||
|
||||
~UdpContext()
|
||||
{
|
||||
}
|
||||
|
||||
void ref()
|
||||
{
|
||||
++_refcnt;
|
||||
}
|
||||
|
||||
void unref()
|
||||
{
|
||||
if(--_refcnt == 0) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
bool connect (ip_addr_t addr, uint16_t port)
|
||||
{
|
||||
_dst = addr;
|
||||
_dstport = port;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool listen(ip_addr_t addr, uint16_t port)
|
||||
{
|
||||
bool ret = mockUDPListen(_sock, addr.addr, port, staticMCastAddr);
|
||||
register_udp(_sock, this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void disconnect()
|
||||
{
|
||||
if (_sock >= 0)
|
||||
{
|
||||
close(_sock);
|
||||
register_udp(_sock, nullptr);
|
||||
}
|
||||
_sock = -1;
|
||||
}
|
||||
|
||||
void setMulticastInterface(const ip_addr_t& addr)
|
||||
{
|
||||
// user multicast, and this is how it works with posix: send to multicast address:
|
||||
_dst.addr = staticMCastAddr;
|
||||
}
|
||||
|
||||
void setMulticastTTL(int ttl)
|
||||
{
|
||||
//fprintf(stderr, MOCK "TODO: UdpContext::setMulticastTTL\n");
|
||||
}
|
||||
|
||||
// warning: handler is called from tcp stack context
|
||||
// esp_yield and non-reentrant functions which depend on it will fail
|
||||
void onRx(rxhandler_t handler) {
|
||||
_on_rx = handler;
|
||||
}
|
||||
|
||||
size_t getSize()
|
||||
{
|
||||
return _inbufsize;
|
||||
}
|
||||
|
||||
size_t tell() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
bool isValidOffset(const size_t pos) const {
|
||||
return pos <= _inbufsize;
|
||||
}
|
||||
|
||||
uint32_t getRemoteAddress()
|
||||
{
|
||||
return _dst.addr;
|
||||
}
|
||||
|
||||
uint16_t getRemotePort()
|
||||
{
|
||||
return _dstport;
|
||||
}
|
||||
|
||||
uint32_t getDestAddress()
|
||||
{
|
||||
fprintf(stderr, MOCK "TODO: implement UDP getDestAddress\n");
|
||||
return 0; //ip_hdr* iphdr = GET_IP_HDR(_rx_buf);
|
||||
}
|
||||
|
||||
uint16_t getLocalPort()
|
||||
{
|
||||
fprintf(stderr, MOCK "TODO: implement UDP getLocalPort\n");
|
||||
return 0; //
|
||||
}
|
||||
|
||||
bool next()
|
||||
{
|
||||
_inbufsize = 0;
|
||||
mockUDPFillInBuf(_sock, _inbuf, _inbufsize, addrsize, addr, _dstport);
|
||||
if (_inbufsize > 0)
|
||||
{
|
||||
translate_addr();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int read()
|
||||
{
|
||||
char c;
|
||||
return read(&c, 1)? c: -1;
|
||||
}
|
||||
|
||||
size_t read(char* dst, size_t size)
|
||||
{
|
||||
return mockUDPRead(_sock, dst, size, _timeout_ms, _inbuf, _inbufsize);
|
||||
}
|
||||
|
||||
int peek()
|
||||
{
|
||||
char c;
|
||||
return mockUDPPeekBytes(_sock, &c, 1, _timeout_ms, _inbuf, _inbufsize)?: -1;
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
//fprintf(stderr, MOCK "UdpContext::flush() does not follow arduino's flush concept\n");
|
||||
//exit(EXIT_FAILURE);
|
||||
// would be:
|
||||
_inbufsize = 0;
|
||||
}
|
||||
|
||||
size_t append (const char* data, size_t size)
|
||||
{
|
||||
if (size + _outbufsize > sizeof _outbuf)
|
||||
{
|
||||
fprintf(stderr, MOCK "UdpContext::append: increase CCBUFSIZE (%d -> %zd)\n", CCBUFSIZE, (size + _outbufsize));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
memcpy(_outbuf + _outbufsize, data, size);
|
||||
_outbufsize += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
bool send (ip_addr_t* addr = 0, uint16_t port = 0)
|
||||
{
|
||||
uint32_t dst = addr? addr->addr: _dst.addr;
|
||||
uint16_t dstport = port?: _dstport;
|
||||
size_t ret = mockUDPWrite(_sock, (const uint8_t*)_outbuf, _outbufsize, _timeout_ms, dst, dstport);
|
||||
_outbufsize = 0;
|
||||
return ret > 0;
|
||||
}
|
||||
|
||||
void mock_cb (void)
|
||||
{
|
||||
if (_on_rx) _on_rx();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static uint32_t staticMCastAddr;
|
||||
|
||||
private:
|
||||
|
||||
void translate_addr ()
|
||||
{
|
||||
if (addrsize == 4)
|
||||
{
|
||||
uint32_t ipv4;
|
||||
memcpy(&ipv4, addr, 4);
|
||||
ip4_addr_set_u32(&ip_2_ip4(_dst), ipv4);
|
||||
// ^ this is a workaround for "type-punned pointer" with "*(uint32*)addr"
|
||||
//ip4_addr_set_u32(&ip_2_ip4(_dst), *(uint32_t*)addr);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, MOCK "TODO unhandled udp address of size %d\n", (int)addrsize);
|
||||
}
|
||||
|
||||
int _sock = -1;
|
||||
rxhandler_t _on_rx;
|
||||
int _refcnt = 0;
|
||||
|
||||
ip_addr_t _dst;
|
||||
uint16_t _dstport;
|
||||
|
||||
char _inbuf [CCBUFSIZE];
|
||||
size_t _inbufsize = 0;
|
||||
char _outbuf [CCBUFSIZE];
|
||||
size_t _outbufsize = 0;
|
||||
|
||||
int _timeout_ms = 0;
|
||||
|
||||
uint8_t addrsize;
|
||||
uint8_t addr[16];
|
||||
};
|
||||
|
||||
inline err_t igmp_joingroup (const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr)
|
||||
{
|
||||
(void)ifaddr;
|
||||
UdpContext::staticMCastAddr = groupaddr->addr;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#endif//UDPCONTEXT_H
|
0
tests/host/common/interrupts.h
Normal file
0
tests/host/common/interrupts.h
Normal file
1
tests/host/common/machine/ansi.h
Normal file
1
tests/host/common/machine/ansi.h
Normal file
@ -0,0 +1 @@
|
||||
/* dummy header file to support BSD compiler */
|
121
tests/host/common/mock.h
Normal file
121
tests/host/common/mock.h
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
Arduino emulation - common to all emulated code
|
||||
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 host's STL before any other include file
|
||||
// because core definition like max() is in the way
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <vector>
|
||||
#endif
|
||||
|
||||
// exotic typedefs used in the sdk
|
||||
|
||||
#include <stdint.h>
|
||||
typedef uint8_t uint8;
|
||||
typedef uint32_t uint32;
|
||||
|
||||
//
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#define RANDOM_REG32 ((uint32_t)random())
|
||||
|
||||
// net tweak
|
||||
|
||||
// htontoh code in common/MockTools.cpp
|
||||
#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
|
||||
#undef INADDR_NONE
|
||||
|
||||
//
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int ets_printf (const char* fmt, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
#define os_printf_plus printf
|
||||
|
||||
extern const char* host_interface; // cmdline parameter
|
||||
|
||||
#define NO_GLOBAL_BINDING 0xffffffff
|
||||
extern uint32_t global_ipv4_netfmt; // selected interface addresse to bind to
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#ifndef CCBUFSIZE
|
||||
#define CCBUFSIZE 8192
|
||||
#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 serverAccept (int sock);
|
||||
|
||||
// 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);
|
||||
|
||||
class UdpContext;
|
||||
void register_udp (int sock, UdpContext* udp = nullptr);
|
||||
|
||||
class InterruptLock { };
|
||||
|
||||
//
|
||||
|
||||
#define CORE_MOCK 1
|
||||
|
||||
#define ARDUINO 267
|
||||
#define ESP8266 1
|
||||
#define A0 0
|
||||
#define LED_BUILTIN 0
|
||||
#define F_CPU 80000000
|
||||
#define LWIP_OPEN_SRC
|
||||
#define TCP_MSS 536
|
||||
#define LWIP_FEATURES 1
|
||||
|
||||
//
|
||||
|
||||
#endif // __cplusplus
|
471
tests/host/common/queue.h
Normal file
471
tests/host/common/queue.h
Normal file
@ -0,0 +1,471 @@
|
||||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
||||
* $FreeBSD: src/sys/sys/queue.h,v 1.48 2002/04/17 14:00:37 tmm Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_QUEUE_H_
|
||||
#define _SYS_QUEUE_H_
|
||||
|
||||
#include <machine/ansi.h> /* for __offsetof */
|
||||
|
||||
/*
|
||||
* This file defines four types of data structures: singly-linked lists,
|
||||
* singly-linked tail queues, lists and tail queues.
|
||||
*
|
||||
* A singly-linked list is headed by a single forward pointer. The elements
|
||||
* are singly linked for minimum space and pointer manipulation overhead at
|
||||
* the expense of O(n) removal for arbitrary elements. New elements can be
|
||||
* added to the list after an existing element or at the head of the list.
|
||||
* Elements being removed from the head of the list should use the explicit
|
||||
* macro for this purpose for optimum efficiency. A singly-linked list may
|
||||
* only be traversed in the forward direction. Singly-linked lists are ideal
|
||||
* for applications with large datasets and few or no removals or for
|
||||
* implementing a LIFO queue.
|
||||
*
|
||||
* A singly-linked tail queue is headed by a pair of pointers, one to the
|
||||
* head of the list and the other to the tail of the list. The elements are
|
||||
* singly linked for minimum space and pointer manipulation overhead at the
|
||||
* expense of O(n) removal for arbitrary elements. New elements can be added
|
||||
* to the list after an existing element, at the head of the list, or at the
|
||||
* end of the list. Elements being removed from the head of the tail queue
|
||||
* should use the explicit macro for this purpose for optimum efficiency.
|
||||
* A singly-linked tail queue may only be traversed in the forward direction.
|
||||
* Singly-linked tail queues are ideal for applications with large datasets
|
||||
* and few or no removals or for implementing a FIFO queue.
|
||||
*
|
||||
* A list is headed by a single forward pointer (or an array of forward
|
||||
* pointers for a hash table header). The elements are doubly linked
|
||||
* so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before
|
||||
* or after an existing element or at the head of the list. A list
|
||||
* may only be traversed in the forward direction.
|
||||
*
|
||||
* A tail queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or
|
||||
* after an existing element, at the head of the list, or at the end of
|
||||
* the list. A tail queue may be traversed in either direction.
|
||||
*
|
||||
* For details on the use of these macros, see the queue(3) manual page.
|
||||
*
|
||||
*
|
||||
* SLIST LIST STAILQ TAILQ
|
||||
* _HEAD + + + +
|
||||
* _HEAD_INITIALIZER + + + +
|
||||
* _ENTRY + + + +
|
||||
* _INIT + + + +
|
||||
* _EMPTY + + + +
|
||||
* _FIRST + + + +
|
||||
* _NEXT + + + +
|
||||
* _PREV - - - +
|
||||
* _LAST - - + +
|
||||
* _FOREACH + + + +
|
||||
* _FOREACH_REVERSE - - - +
|
||||
* _INSERT_HEAD + + + +
|
||||
* _INSERT_BEFORE - + - +
|
||||
* _INSERT_AFTER + + + +
|
||||
* _INSERT_TAIL - - + +
|
||||
* _CONCAT - - + +
|
||||
* _REMOVE_HEAD + - + -
|
||||
* _REMOVE + + + +
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Singly-linked List declarations.
|
||||
*/
|
||||
#define SLIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *slh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define SLIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define SLIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sle_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked List functions.
|
||||
*/
|
||||
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
|
||||
|
||||
#define SLIST_FIRST(head) ((head)->slh_first)
|
||||
|
||||
#define SLIST_FOREACH(var, head, field) \
|
||||
for ((var) = SLIST_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = SLIST_NEXT((var), field))
|
||||
|
||||
#define SLIST_INIT(head) do { \
|
||||
SLIST_FIRST((head)) = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
|
||||
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
|
||||
SLIST_NEXT((slistelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_INSERT_HEAD(head, elm, field) do { \
|
||||
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
|
||||
SLIST_FIRST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
||||
|
||||
#define SLIST_REMOVE(head, elm, type, field) do { \
|
||||
if (SLIST_FIRST((head)) == (elm)) { \
|
||||
SLIST_REMOVE_HEAD((head), field); \
|
||||
} \
|
||||
else { \
|
||||
struct type *curelm = SLIST_FIRST((head)); \
|
||||
while (SLIST_NEXT(curelm, field) != (elm)) \
|
||||
curelm = SLIST_NEXT(curelm, field); \
|
||||
SLIST_NEXT(curelm, field) = \
|
||||
SLIST_NEXT(SLIST_NEXT(curelm, field), field); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_REMOVE_HEAD(head, field) do { \
|
||||
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue declarations.
|
||||
*/
|
||||
#define STAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *stqh_first;/* first element */ \
|
||||
struct type **stqh_last;/* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define STAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).stqh_first }
|
||||
|
||||
#define STAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *stqe_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue functions.
|
||||
*/
|
||||
#define STAILQ_CONCAT(head1, head2) do { \
|
||||
if (!STAILQ_EMPTY((head2))) { \
|
||||
*(head1)->stqh_last = (head2)->stqh_first; \
|
||||
(head1)->stqh_last = (head2)->stqh_last; \
|
||||
STAILQ_INIT((head2)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
|
||||
|
||||
#define STAILQ_FIRST(head) ((head)->stqh_first)
|
||||
|
||||
#define STAILQ_FOREACH(var, head, field) \
|
||||
for((var) = STAILQ_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = STAILQ_NEXT((var), field))
|
||||
|
||||
#define STAILQ_INIT(head) do { \
|
||||
STAILQ_FIRST((head)) = NULL; \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
|
||||
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
STAILQ_NEXT((tqelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
STAILQ_FIRST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
STAILQ_NEXT((elm), field) = NULL; \
|
||||
*(head)->stqh_last = (elm); \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_LAST(head, type, field) \
|
||||
(STAILQ_EMPTY((head)) ? \
|
||||
NULL : \
|
||||
((struct type *) \
|
||||
((char *)((head)->stqh_last) - __offsetof(struct type, field))))
|
||||
|
||||
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
|
||||
|
||||
#define STAILQ_REMOVE(head, elm, type, field) do { \
|
||||
if (STAILQ_FIRST((head)) == (elm)) { \
|
||||
STAILQ_REMOVE_HEAD((head), field); \
|
||||
} \
|
||||
else { \
|
||||
struct type *curelm = STAILQ_FIRST((head)); \
|
||||
while (STAILQ_NEXT(curelm, field) != (elm)) \
|
||||
curelm = STAILQ_NEXT(curelm, field); \
|
||||
if ((STAILQ_NEXT(curelm, field) = \
|
||||
STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
|
||||
(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD(head, field) do { \
|
||||
if ((STAILQ_FIRST((head)) = \
|
||||
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
|
||||
if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* List declarations.
|
||||
*/
|
||||
#define LIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *lh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define LIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define LIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *le_next; /* next element */ \
|
||||
struct type **le_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* List functions.
|
||||
*/
|
||||
|
||||
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
|
||||
|
||||
#define LIST_FIRST(head) ((head)->lh_first)
|
||||
|
||||
#define LIST_FOREACH(var, head, field) \
|
||||
for ((var) = LIST_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = LIST_NEXT((var), field))
|
||||
|
||||
#define LIST_INIT(head) do { \
|
||||
LIST_FIRST((head)) = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
|
||||
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
|
||||
LIST_NEXT((listelm), field)->field.le_prev = \
|
||||
&LIST_NEXT((elm), field); \
|
||||
LIST_NEXT((listelm), field) = (elm); \
|
||||
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.le_prev = (listelm)->field.le_prev; \
|
||||
LIST_NEXT((elm), field) = (listelm); \
|
||||
*(listelm)->field.le_prev = (elm); \
|
||||
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
|
||||
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
|
||||
LIST_FIRST((head)) = (elm); \
|
||||
(elm)->field.le_prev = &LIST_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
|
||||
|
||||
#define LIST_REMOVE(elm, field) do { \
|
||||
if (LIST_NEXT((elm), field) != NULL) \
|
||||
LIST_NEXT((elm), field)->field.le_prev = \
|
||||
(elm)->field.le_prev; \
|
||||
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Tail queue declarations.
|
||||
*/
|
||||
#define TAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *tqh_first; /* first element */ \
|
||||
struct type **tqh_last; /* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define TAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).tqh_first }
|
||||
|
||||
#define TAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *tqe_next; /* next element */ \
|
||||
struct type **tqe_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Tail queue functions.
|
||||
*/
|
||||
#define TAILQ_CONCAT(head1, head2, field) do { \
|
||||
if (!TAILQ_EMPTY(head2)) { \
|
||||
*(head1)->tqh_last = (head2)->tqh_first; \
|
||||
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
|
||||
(head1)->tqh_last = (head2)->tqh_last; \
|
||||
TAILQ_INIT((head2)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
|
||||
|
||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||
|
||||
#define TAILQ_FOREACH(var, head, field) \
|
||||
for ((var) = TAILQ_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = TAILQ_NEXT((var), field))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
|
||||
for ((var) = TAILQ_LAST((head), headname); \
|
||||
(var); \
|
||||
(var) = TAILQ_PREV((var), headname, field))
|
||||
|
||||
#define TAILQ_INIT(head) do { \
|
||||
TAILQ_FIRST((head)) = NULL; \
|
||||
(head)->tqh_last = &TAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
|
||||
TAILQ_NEXT((elm), field)->field.tqe_prev = \
|
||||
&TAILQ_NEXT((elm), field); \
|
||||
else \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
TAILQ_NEXT((listelm), field) = (elm); \
|
||||
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
|
||||
TAILQ_NEXT((elm), field) = (listelm); \
|
||||
*(listelm)->field.tqe_prev = (elm); \
|
||||
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
|
||||
TAILQ_FIRST((head))->field.tqe_prev = \
|
||||
&TAILQ_NEXT((elm), field); \
|
||||
else \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
TAILQ_FIRST((head)) = (elm); \
|
||||
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
TAILQ_NEXT((elm), field) = NULL; \
|
||||
(elm)->field.tqe_prev = (head)->tqh_last; \
|
||||
*(head)->tqh_last = (elm); \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_LAST(head, headname) \
|
||||
(*(((struct headname *)((head)->tqh_last))->tqh_last))
|
||||
|
||||
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||
|
||||
#define TAILQ_PREV(elm, headname, field) \
|
||||
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
|
||||
|
||||
#define TAILQ_REMOVE(head, elm, field) do { \
|
||||
if ((TAILQ_NEXT((elm), field)) != NULL) \
|
||||
TAILQ_NEXT((elm), field)->field.tqe_prev = \
|
||||
(elm)->field.tqe_prev; \
|
||||
else \
|
||||
(head)->tqh_last = (elm)->field.tqe_prev; \
|
||||
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
/*
|
||||
* XXX insque() and remque() are an old way of handling certain queues.
|
||||
* They bogusly assumes that all queue heads look alike.
|
||||
*/
|
||||
|
||||
struct quehead {
|
||||
struct quehead *qh_link;
|
||||
struct quehead *qh_rlink;
|
||||
};
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
static __inline void
|
||||
insque(void *a, void *b)
|
||||
{
|
||||
struct quehead *element = (struct quehead *)a,
|
||||
*head = (struct quehead *)b;
|
||||
|
||||
element->qh_link = head->qh_link;
|
||||
element->qh_rlink = head;
|
||||
head->qh_link = element;
|
||||
element->qh_link->qh_rlink = element;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
remque(void *a)
|
||||
{
|
||||
struct quehead *element = (struct quehead *)a;
|
||||
|
||||
element->qh_link->qh_rlink = element->qh_rlink;
|
||||
element->qh_rlink->qh_link = element->qh_link;
|
||||
element->qh_rlink = 0;
|
||||
}
|
||||
|
||||
#else /* !__GNUC__ */
|
||||
|
||||
void insque(void *a, void *b);
|
||||
void remque(void *a);
|
||||
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !_SYS_QUEUE_H_ */
|
@ -22,6 +22,13 @@
|
||||
|
||||
#include <spiffs_api.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define SPIFFS_FILE_NAME "spiffs.bin"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
static uint32_t s_phys_addr = 0;
|
||||
@ -33,32 +40,89 @@ extern "C"
|
||||
|
||||
FS SPIFFS(nullptr);
|
||||
|
||||
SpiffsMock::SpiffsMock(size_t fs_size, size_t fs_block, size_t fs_page)
|
||||
SpiffsMock::SpiffsMock(size_t fs_size, size_t fs_block, size_t fs_page, bool storage)
|
||||
{
|
||||
m_fs.resize(fs_size, 0xff);
|
||||
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);
|
||||
|
||||
s_phys_addr = 0;
|
||||
s_phys_size = static_cast<uint32_t>(fs_size);
|
||||
s_phys_page = static_cast<uint32_t>(fs_page);
|
||||
s_phys_block = static_cast<uint32_t>(fs_block);
|
||||
s_phys_data = m_fs.data();
|
||||
s_phys_data = &m_fs[0];
|
||||
reset();
|
||||
}
|
||||
|
||||
void SpiffsMock::reset()
|
||||
{
|
||||
SPIFFS = FS(FSImplPtr(new SPIFFSImpl(0, s_phys_size, s_phys_page, s_phys_block, 5)));
|
||||
if (m_storage)
|
||||
load();
|
||||
}
|
||||
|
||||
SpiffsMock::~SpiffsMock()
|
||||
{
|
||||
if (m_storage)
|
||||
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;
|
||||
SPIFFS = FS(FSImplPtr(nullptr));
|
||||
}
|
||||
|
||||
void SpiffsMock::load ()
|
||||
{
|
||||
if (!m_fs_size)
|
||||
return;
|
||||
|
||||
const char* fname = getenv("SPIFFS_PATH");
|
||||
if (!fname)
|
||||
fname = DEFAULT_SPIFFS_FILE_NAME;
|
||||
int fs = ::open(SPIFFS_FILE_NAME, O_RDONLY);
|
||||
if (fs == -1)
|
||||
{
|
||||
fprintf(stderr, "SPIFFS: loading '%s': %s\n", fname, 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));
|
||||
::close(fs);
|
||||
}
|
||||
|
||||
void SpiffsMock::save ()
|
||||
{
|
||||
if (!m_fs_size)
|
||||
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);
|
||||
if (fs == -1)
|
||||
{
|
||||
fprintf(stderr, "SPIFFS: saving '%s': %s\n", fname, 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]);
|
||||
|
||||
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 (::close(fs) == -1)
|
||||
fprintf(stderr, "SPIFFS: closing %s: %s\n", fname, strerror(errno));
|
||||
}
|
||||
|
||||
int32_t spiffs_hal_read(uint32_t addr, uint32_t size, uint8_t *dst) {
|
||||
memcpy(dst, s_phys_data + addr, size);
|
||||
return SPIFFS_OK;
|
||||
|
@ -21,17 +21,32 @@
|
||||
#include <vector>
|
||||
#include <FS.h>
|
||||
|
||||
#define DEFAULT_SPIFFS_FILE_NAME "spiffs.bin"
|
||||
|
||||
class SpiffsMock {
|
||||
public:
|
||||
SpiffsMock(size_t fs_size, size_t fs_block, size_t fs_page);
|
||||
SpiffsMock(size_t fs_size, size_t fs_block, size_t fs_page, bool storage = true);
|
||||
void reset();
|
||||
~SpiffsMock();
|
||||
|
||||
protected:
|
||||
std::vector<uint8_t> m_fs;
|
||||
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;
|
||||
};
|
||||
|
||||
#define SPIFFS_MOCK_DECLARE(size_kb, block_kb, page_b) SpiffsMock spiffs_mock(size_kb * 1024, block_kb * 1024, page_b)
|
||||
#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()
|
||||
|
||||
|
||||
|
458
tests/host/common/user_interface.cpp
Normal file
458
tests/host/common/user_interface.cpp
Normal file
@ -0,0 +1,458 @@
|
||||
/*
|
||||
Arduino emulation - espressif sdk host implementation
|
||||
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/def.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#include <user_interface.h>
|
||||
|
||||
uint8 wifi_get_opmode(void)
|
||||
{
|
||||
return STATION_MODE;
|
||||
}
|
||||
|
||||
phy_mode_t wifi_get_phy_mode(void)
|
||||
{
|
||||
return PHY_MODE_11N;
|
||||
}
|
||||
|
||||
uint8 wifi_get_channel (void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8 wifi_station_get_current_ap_id (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
station_status_t wifi_station_get_connect_status (void)
|
||||
{
|
||||
return STATION_GOT_IP;
|
||||
}
|
||||
|
||||
uint8 wifi_station_get_auto_connect (void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool wifi_station_get_config (struct station_config *config)
|
||||
{
|
||||
strcpy((char*)config->ssid, "emulated-ssid");
|
||||
strcpy((char*)config->password, "emulated-ssid-password");
|
||||
config->bssid_set = 0;
|
||||
for (int i = 0; i < 6; i++)
|
||||
config->bssid[i] = i;
|
||||
config->threshold.rssi = 1;
|
||||
config->threshold.authmode = AUTH_WPA_PSK;
|
||||
config->open_and_wep_mode_disable = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void wifi_fpm_close(void)
|
||||
{
|
||||
}
|
||||
|
||||
sint8 wifi_fpm_do_sleep (uint32 sleep_time_in_us)
|
||||
{
|
||||
usleep(sleep_time_in_us);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void wifi_fpm_do_wakeup (void)
|
||||
{
|
||||
}
|
||||
|
||||
void wifi_fpm_open (void)
|
||||
{
|
||||
}
|
||||
|
||||
void wifi_fpm_set_sleep_type (sleep_type_t type)
|
||||
{
|
||||
(void)type;
|
||||
}
|
||||
|
||||
uint32_t global_ipv4_netfmt = 0; // global binding
|
||||
|
||||
bool wifi_get_ip_info (uint8 if_index, struct ip_info *info)
|
||||
{
|
||||
struct ifaddrs * ifAddrStruct = NULL, * ifa = NULL;
|
||||
uint32_t ipv4 = lwip_htonl(0x7f000001);
|
||||
uint32_t mask = lwip_htonl(0xff000000);
|
||||
|
||||
if (getifaddrs(&ifAddrStruct) != 0)
|
||||
{
|
||||
perror("getifaddrs");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next)
|
||||
{
|
||||
if ( ifa->ifa_addr
|
||||
&& ifa->ifa_addr->sa_family == AF_INET // ip_info is IPv4 only
|
||||
)
|
||||
{
|
||||
if (lwip_ntohl(*(uint32_t*)&((struct sockaddr_in*) ifa->ifa_netmask)->sin_addr) != 0xff000000)
|
||||
{
|
||||
if (ipv4 == lwip_htonl(0x7f000001))
|
||||
{
|
||||
// take the first by default
|
||||
ipv4 = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_addr)->sin_addr;
|
||||
mask = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr;
|
||||
}
|
||||
if (host_interface && strcmp(ifa->ifa_name, host_interface) == 0)
|
||||
{
|
||||
// .. or the one specified by user on cmdline
|
||||
ipv4 = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_addr)->sin_addr;
|
||||
mask = *(uint32_t*)&((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ifAddrStruct != NULL)
|
||||
freeifaddrs(ifAddrStruct);
|
||||
|
||||
(void)if_index;
|
||||
//if (if_index != STATION_IF)
|
||||
// fprintf(stderr, "we are not AP");
|
||||
|
||||
if (global_ipv4_netfmt == NO_GLOBAL_BINDING)
|
||||
global_ipv4_netfmt = ipv4;
|
||||
|
||||
if (info)
|
||||
{
|
||||
info->ip.addr = ipv4;
|
||||
info->netmask.addr = mask;
|
||||
info->gw.addr = ipv4;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8 wifi_get_listen_interval (void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool wifi_get_macaddr(uint8 if_index, uint8 *macaddr)
|
||||
{
|
||||
macaddr[0] = 0xde;
|
||||
macaddr[1] = 0xba;
|
||||
macaddr[2] = 0x7a;
|
||||
macaddr[3] = 0xb1;
|
||||
macaddr[4] = 0xe0;
|
||||
macaddr[5] = 0x42;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8 wifi_get_opmode_default (void)
|
||||
{
|
||||
return STATION_MODE;
|
||||
}
|
||||
|
||||
sleep_level_t wifi_get_sleep_level (void)
|
||||
{
|
||||
return MIN_SLEEP_T;
|
||||
}
|
||||
|
||||
sleep_type_t wifi_get_sleep_type (void)
|
||||
{
|
||||
return NONE_SLEEP_T;
|
||||
}
|
||||
|
||||
bool wifi_set_channel (uint8 channel)
|
||||
{
|
||||
(void)channel;
|
||||
return true;
|
||||
}
|
||||
|
||||
wifi_event_handler_cb_t wifi_event_handler_cb_emu = nullptr;
|
||||
void wifi_set_event_handler_cb (wifi_event_handler_cb_t cb)
|
||||
{
|
||||
wifi_event_handler_cb_emu = cb;
|
||||
fprintf(stderr, MOCK "TODO: wifi_set_event_handler_cb set\n");
|
||||
}
|
||||
|
||||
bool wifi_set_ip_info (uint8 if_index, struct ip_info *info)
|
||||
{
|
||||
(void)if_index;
|
||||
(void)info;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wifi_set_listen_interval (uint8 interval)
|
||||
{
|
||||
(void)interval;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_set_opmode (uint8 opmode)
|
||||
{
|
||||
return opmode == STATION_MODE || opmode == STATIONAP_MODE;
|
||||
}
|
||||
|
||||
bool wifi_set_opmode_current (uint8 opmode)
|
||||
{
|
||||
return opmode == STATION_MODE || opmode == STATIONAP_MODE;
|
||||
}
|
||||
|
||||
bool wifi_set_phy_mode (phy_mode_t mode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_set_sleep_level (sleep_level_t level)
|
||||
{
|
||||
(void)level;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_set_sleep_type (sleep_type_t type)
|
||||
{
|
||||
(void)type;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_station_connect (void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_station_dhcpc_start (void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_station_dhcpc_stop (void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_station_disconnect (void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_station_get_config_default (struct station_config *config)
|
||||
{
|
||||
return wifi_station_get_config(config);
|
||||
}
|
||||
|
||||
char wifi_station_get_hostname_str [128];
|
||||
char* wifi_station_get_hostname (void)
|
||||
{
|
||||
return strcpy(wifi_station_get_hostname_str, "esposix");
|
||||
}
|
||||
|
||||
bool wifi_station_get_reconnect_policy ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
sint8 wifi_station_get_rssi (void)
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
bool wifi_station_set_auto_connect (uint8 set)
|
||||
{
|
||||
return set != 0;
|
||||
}
|
||||
|
||||
bool wifi_station_set_config (struct station_config *config)
|
||||
{
|
||||
(void)config;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_station_set_config_current (struct station_config *config)
|
||||
{
|
||||
(void)config;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_station_set_hostname (char *name)
|
||||
{
|
||||
(void)name;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_station_set_reconnect_policy (bool set)
|
||||
{
|
||||
(void)set;
|
||||
return true;
|
||||
}
|
||||
|
||||
void system_phy_set_max_tpw (uint8 max_tpw)
|
||||
{
|
||||
(void)max_tpw;
|
||||
}
|
||||
|
||||
bool wifi_softap_dhcps_start(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
enum dhcp_status wifi_softap_dhcps_status(void)
|
||||
{
|
||||
return DHCP_STARTED;
|
||||
}
|
||||
|
||||
bool wifi_softap_dhcps_stop(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_softap_get_config(struct softap_config *config)
|
||||
{
|
||||
strcpy((char*)config->ssid, "apssid");
|
||||
strcpy((char*)config->password, "appasswd");
|
||||
config->ssid_len = strlen("appasswd");
|
||||
config->channel = 1;
|
||||
config->authmode = AUTH_WPA2_PSK;
|
||||
config->ssid_hidden = 0;
|
||||
config->max_connection = 4;
|
||||
config->beacon_interval = 100;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_softap_get_config_default(struct softap_config *config)
|
||||
{
|
||||
return wifi_softap_get_config(config);
|
||||
}
|
||||
|
||||
uint8 wifi_softap_get_station_num(void)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
bool wifi_softap_set_config(struct softap_config *config)
|
||||
{
|
||||
(void)config;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_softap_set_config_current(struct softap_config *config)
|
||||
{
|
||||
(void)config;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_softap_set_dhcps_lease(struct dhcps_lease *please)
|
||||
{
|
||||
(void)please;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_softap_set_dhcps_lease_time(uint32 minute)
|
||||
{
|
||||
(void)minute;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_softap_set_dhcps_offer_option(uint8 level, void* optarg)
|
||||
{
|
||||
(void)level;
|
||||
(void)optarg;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_station_scan(struct scan_config *config, scan_done_cb_t cb)
|
||||
{
|
||||
cb(nullptr, FAIL);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t core_version = 1;
|
||||
|
||||
///////////////////////////////////////
|
||||
// not user_interface
|
||||
|
||||
void ets_isr_mask (int intr)
|
||||
{
|
||||
(void)intr;
|
||||
}
|
||||
|
||||
void ets_isr_unmask (int intr)
|
||||
{
|
||||
(void)intr;
|
||||
}
|
||||
|
||||
void esp_schedule (void)
|
||||
{
|
||||
}
|
||||
|
||||
void optimistic_yield (uint32_t ms)
|
||||
{
|
||||
usleep(ms * 1000);
|
||||
}
|
||||
|
||||
void dns_setserver (u8_t numdns, ip_addr_t *dnsserver)
|
||||
{
|
||||
(void)numdns;
|
||||
(void)dnsserver;
|
||||
}
|
||||
|
||||
ip_addr_t dns_getserver (u8_t numdns)
|
||||
{
|
||||
ip_addr_t addr = { 0x7f000001 };
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
#include <smartconfig.h>
|
||||
bool smartconfig_start (sc_callback_t cb, ...)
|
||||
{
|
||||
//XXXFIXME ... -> ptr
|
||||
cb(SC_STATUS_LINK, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool smartconfig_stop (void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // extern "C"
|
@ -50,25 +50,25 @@ static std::set<String> listDir (const char* path)
|
||||
|
||||
TEST_CASE("FS can begin","[fs]")
|
||||
{
|
||||
SPIFFS_MOCK_DECLARE(64, 8, 512);
|
||||
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||
REQUIRE(SPIFFS.begin());
|
||||
}
|
||||
|
||||
TEST_CASE("FS can't begin with zero size","[fs]")
|
||||
{
|
||||
SPIFFS_MOCK_DECLARE(0, 8, 512);
|
||||
SPIFFS_MOCK_DECLARE(0, 8, 512, false);
|
||||
REQUIRE_FALSE(SPIFFS.begin());
|
||||
}
|
||||
|
||||
TEST_CASE("Before begin is called, open will fail","[fs]")
|
||||
{
|
||||
SPIFFS_MOCK_DECLARE(64, 8, 512);
|
||||
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||
REQUIRE_FALSE(SPIFFS.open("/foo", "w"));
|
||||
}
|
||||
|
||||
TEST_CASE("FS can create file","[fs]")
|
||||
{
|
||||
SPIFFS_MOCK_DECLARE(64, 8, 512);
|
||||
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||
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);
|
||||
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||
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);
|
||||
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||
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);
|
||||
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||
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);
|
||||
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||
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);
|
||||
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||
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);
|
||||
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||
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);
|
||||
SPIFFS_MOCK_DECLARE(64, 8, 512, false);
|
||||
REQUIRE(SPIFFS.begin());
|
||||
createFile("/file1", "some text");
|
||||
createFile("/file2", "other text");
|
||||
|
@ -11,7 +11,7 @@ install: all version-header
|
||||
|
||||
bearssl/README.txt:
|
||||
git submodule update --init --recursive bearssl
|
||||
cd bearssl && git remote add bearssl https://www.bearssl.org/git/BearSSL
|
||||
cd bearssl && (git remote add bearssl https://www.bearssl.org/git/BearSSL || true)
|
||||
|
||||
merge-upstream:
|
||||
cd bearssl && git pull bearssl master
|
||||
@ -20,3 +20,9 @@ version-header:
|
||||
echo "// Do not edit -- Automatically generated by tools/sdk/ssl/bearssl/Makefile" > $(VER_H)
|
||||
echo -n "#define BEARSSL_GIT " >> $(VER_H)
|
||||
cd bearssl && git rev-parse --short HEAD >> ../$(VER_H)
|
||||
|
||||
native: bearssl/README.txt
|
||||
cd bearssl && make
|
||||
|
||||
native32: bearssl/README.txt
|
||||
cd bearssl && make CONF=Unix32
|
||||
|
Loading…
x
Reference in New Issue
Block a user