From 022e66c8e01bb4a9ac1a7c1ca23ec4d69f302f71 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Thu, 8 Nov 2018 17:23:26 +0100 Subject: [PATCH 01/50] WIP compile examples on host with 'make examples' --- tests/host/Makefile | 44 +++ tests/host/core-mock/machine/ansi.h | 1 + tests/host/core-mock/mock.h | 9 + tests/host/core-mock/queue.h | 471 ++++++++++++++++++++++++++ tests/host/core-mock/user_interface.h | 3 + 5 files changed, 528 insertions(+) create mode 100644 tests/host/core-mock/machine/ansi.h create mode 100644 tests/host/core-mock/mock.h create mode 100644 tests/host/core-mock/queue.h create mode 100644 tests/host/core-mock/user_interface.h diff --git a/tests/host/Makefile b/tests/host/Makefile index 036ed18fcc..4c7bf37c12 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -123,3 +123,47 @@ $(BINARY_DIRECTORY)/core.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE) $(OUTPUT_BINARY): $(BINARY_DIRECTORY) $(CPP_OBJECTS_TESTS) $(BINARY_DIRECTORY)/core.a $(CXX) $(LDFLAGS) $(CPP_OBJECTS_TESTS) $(BINARY_DIRECTORY)/core.a $(LIBS) -o $(OUTPUT_BINARY) + +################################################# +# building ino sources +-include Makefile.inc.ino + +%.ino-host: %.ino-host.o + +SDK_PATH := core-mock ../../tools/sdk/include +CORE_LIB_PATH := ../../libraries/ESP8266WiFi/src + +INC_CORE_PATHS += $(addprefix -I, \ + $(CORE_LIB_PATH) \ + $(SDK_PATH) \ +) + +%.ino-host.o: %.ino-host.cpp + $(CXX) -include core-mock/mock.h $(CXXFLAGS) $(INC_PATHS) $(INC_CORE_PATHS) -c -o $@ $< + +.PRECIOUS: %-host.cpp +%.ino-host.cpp: %.ino + cp $< $@ + +################################################# +# Makefile.inc.ino generation + +# default "examples" rule (overridden in Makefile.inc.ino when built) +.PHONY: examples +examples: + # copy examples locally + rm -f Makefile.inc.ino + all=""; \ + for dir in ../../libraries/*/examples; do \ + exampledir=$${dir%/*}; \ + exampledirname=$${exampledir##*/}; \ + for subdir in $$dir/*; do \ + exname=$${subdir##*/}; \ + mkdir -p examples/$$exampledirname/$$exname; \ + (cd $$subdir && tar cf - .) | (cd examples/$$exampledirname/$$exname; tar xf -); \ + echo examples/$$exampledirname/$$exname/$$exname-host: examples/$$exampledirname/$$exname/$$exname.ino >> Makefile.inc.ino; \ + all="$$all examples/$$exampledirname/$$exname/$$exname.ino-host"; \ + done; \ + done; \ + echo "$@: $$all" >> Makefile.inc.ino + $(MAKE) $@ diff --git a/tests/host/core-mock/machine/ansi.h b/tests/host/core-mock/machine/ansi.h new file mode 100644 index 0000000000..737b6d0666 --- /dev/null +++ b/tests/host/core-mock/machine/ansi.h @@ -0,0 +1 @@ +/* dummy header file to support BSD compiler */ diff --git a/tests/host/core-mock/mock.h b/tests/host/core-mock/mock.h new file mode 100644 index 0000000000..5e741d6a26 --- /dev/null +++ b/tests/host/core-mock/mock.h @@ -0,0 +1,9 @@ + +// include host's STL before any other include file +// because core definition like max() is in the way +#include + +// exotic typedefs used in the sdk +#include +typedef uint8_t uint8; +typedef uint32_t uint32; diff --git a/tests/host/core-mock/queue.h b/tests/host/core-mock/queue.h new file mode 100644 index 0000000000..af637ca030 --- /dev/null +++ b/tests/host/core-mock/queue.h @@ -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 /* 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_ */ diff --git a/tests/host/core-mock/user_interface.h b/tests/host/core-mock/user_interface.h new file mode 100644 index 0000000000..758fe9e512 --- /dev/null +++ b/tests/host/core-mock/user_interface.h @@ -0,0 +1,3 @@ + +// mock user_interface.h + From d7bd8dbfb6319ecf5db94c6b826a8cfc6ac862f8 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Fri, 9 Nov 2018 17:24:43 +0100 Subject: [PATCH 02/50] WIP --- tests/host/Makefile | 58 ++++++++++------ tests/host/common/Arduino.cpp | 2 - tests/host/common/Arduino.h | 2 + tests/host/common/ArduinoCatch.cpp | 20 ++++++ tests/host/common/ArduinoMain.cpp | 16 +++++ tests/host/common/HardwareSerial.cpp | 66 +++++++++++++++++++ tests/host/common/WMath.cpp | 4 +- .../host/{core-mock => common}/machine/ansi.h | 0 tests/host/{core-mock => common}/mock.h | 7 ++ tests/host/{core-mock => common}/queue.h | 0 .../{core-mock => common}/user_interface.h | 0 11 files changed, 151 insertions(+), 24 deletions(-) create mode 100644 tests/host/common/ArduinoCatch.cpp create mode 100644 tests/host/common/ArduinoMain.cpp create mode 100644 tests/host/common/HardwareSerial.cpp rename tests/host/{core-mock => common}/machine/ansi.h (100%) rename tests/host/{core-mock => common}/mock.h (88%) rename tests/host/{core-mock => common}/queue.h (100%) rename tests/host/{core-mock => common}/user_interface.h (100%) diff --git a/tests/host/Makefile b/tests/host/Makefile index 4c7bf37c12..15dc68d7e2 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -2,6 +2,12 @@ BINARY_DIRECTORY := bin LCOV_DIRECTORY := lcov OUTPUT_BINARY := $(BINARY_DIRECTORY)/host_tests CORE_PATH := ../../cores/esp8266 +OPT := -O0 + +INC_PATHS += $(addprefix -I,\ + $(shell echo ../../libraries/*/src) \ + $(shell echo ../../libraries/*) \ +) # I wasn't able to build with clang when -coverage flag is enabled, forcing GCC on OS X ifeq ($(shell uname -s),Darwin) @@ -33,10 +39,19 @@ CORE_C_FILES := $(addprefix $(CORE_PATH)/,\ spiffs/spiffs_nucleus.c \ ) -MOCK_CPP_FILES := $(addprefix common/,\ +MOCK_CPP_FILES_COMMON := $(addprefix common/,\ Arduino.cpp \ spiffs_mock.cpp \ WMath.cpp \ + HardwareSerial.cpp \ +) + +MOCK_CPP_FILES := $(MOCK_CPP_FILES_COMMON) $(addprefix common/,\ + ArduinoCatch.cpp \ +) + +MOCK_CPP_FILES_EMU := $(MOCK_CPP_FILES_COMMON) $(addprefix common/,\ + ArduinoMain.cpp \ ) MOCK_C_FILES := $(addprefix common/,\ @@ -47,6 +62,7 @@ MOCK_C_FILES := $(addprefix common/,\ INC_PATHS += $(addprefix -I, \ common \ $(CORE_PATH) \ + ../../tools/sdk/include \ ) TEST_CPP_FILES := \ @@ -111,11 +127,13 @@ build-info: $(BINARY_DIRECTORY): mkdir -p $@ -$(C_OBJECTS): %.c.o: %.c +#$(C_OBJECTS): %.c.o: %.c +%.c.o: %.c $(CC) $(CFLAGS) $(INC_PATHS) -c -o $@ $< -$(CPP_OBJECTS): %.cpp.o: %.cpp - $(CXX) $(CXXFLAGS) $(INC_PATHS) -c -o $@ $< +#$(CPP_OBJECTS): %.cpp.o: %.cpp +%.cpp.o: %.cpp + $(CXX) -include common/mock.h $(CXXFLAGS) $(INC_PATHS) -c -o $@ $< $(BINARY_DIRECTORY)/core.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE) ar -rcu $@ $(C_OBJECTS) $(CPP_OBJECTS_CORE) @@ -126,20 +144,19 @@ $(OUTPUT_BINARY): $(BINARY_DIRECTORY) $(CPP_OBJECTS_TESTS) $(BINARY_DIRECTORY)/c ################################################# # building ino sources --include Makefile.inc.ino +-include examples/Makefile.inc.ino -%.ino-host: %.ino-host.o +CPP_OBJECTS_CORE_EMU = $(MOCK_CPP_FILES_EMU:.cpp=.cpp.o) $(CORE_CPP_FILES:.cpp=.cpp.o) -SDK_PATH := core-mock ../../tools/sdk/include -CORE_LIB_PATH := ../../libraries/ESP8266WiFi/src +common/fullcore.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE_EMU) + ar -rcu $@ $^ + ranlib -c $@ -INC_CORE_PATHS += $(addprefix -I, \ - $(CORE_LIB_PATH) \ - $(SDK_PATH) \ -) +%.ino-host: %.ino-host.o common/fullcore.a + $(CXX) $(LDFLAGS) $^ -o $@ %.ino-host.o: %.ino-host.cpp - $(CXX) -include core-mock/mock.h $(CXXFLAGS) $(INC_PATHS) $(INC_CORE_PATHS) -c -o $@ $< + $(CXX) -include common/mock.h $(CXXFLAGS) $(INC_PATHS) -c -o $@ $< .PRECIOUS: %-host.cpp %.ino-host.cpp: %.ino @@ -148,22 +165,23 @@ INC_CORE_PATHS += $(addprefix -I, \ ################################################# # Makefile.inc.ino generation -# default "examples" rule (overridden in Makefile.inc.ino when built) .PHONY: examples + +# default "examples" rule (overridden in Makefile.inc.ino when built) examples: # copy examples locally rm -f Makefile.inc.ino all=""; \ - for dir in ../../libraries/*/examples; do \ + for dir in ../../libraries/*/$@; do \ exampledir=$${dir%/*}; \ exampledirname=$${exampledir##*/}; \ for subdir in $$dir/*; do \ exname=$${subdir##*/}; \ - mkdir -p examples/$$exampledirname/$$exname; \ - (cd $$subdir && tar cf - .) | (cd examples/$$exampledirname/$$exname; tar xf -); \ - echo examples/$$exampledirname/$$exname/$$exname-host: examples/$$exampledirname/$$exname/$$exname.ino >> Makefile.inc.ino; \ - all="$$all examples/$$exampledirname/$$exname/$$exname.ino-host"; \ + mkdir -p $@/$$exampledirname/$$exname; \ + (cd $$subdir && tar cf - .) | (cd $@/$$exampledirname/$$exname; tar xf -); \ + echo $@/$$exampledirname/$$exname/$$exname-host: $@/$$exampledirname/$$exname/$$exname.ino >> $@/Makefile.inc.ino; \ + all="$$all $@/$$exampledirname/$$exname/$$exname.ino-host"; \ done; \ done; \ - echo "$@: $$all" >> Makefile.inc.ino + echo "$@: $$all" >> $@/Makefile.inc.ino $(MAKE) $@ diff --git a/tests/host/common/Arduino.cpp b/tests/host/common/Arduino.cpp index c1b141bc73..e3d6eccefc 100644 --- a/tests/host/common/Arduino.cpp +++ b/tests/host/common/Arduino.cpp @@ -13,8 +13,6 @@ all copies or substantial portions of the Software. */ -#define CATCH_CONFIG_MAIN -#include #include #include "Arduino.h" diff --git a/tests/host/common/Arduino.h b/tests/host/common/Arduino.h index e68565ee82..34b6dc2402 100644 --- a/tests/host/common/Arduino.h +++ b/tests/host/common/Arduino.h @@ -20,6 +20,8 @@ #ifndef Arduino_h #define Arduino_h +#define MOCK "mock: " + #ifdef __cplusplus extern "C" { #endif diff --git a/tests/host/common/ArduinoCatch.cpp b/tests/host/common/ArduinoCatch.cpp new file mode 100644 index 0000000000..6a1e3cca23 --- /dev/null +++ b/tests/host/common/ArduinoCatch.cpp @@ -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 +#include +#include "Arduino.h" + diff --git a/tests/host/common/ArduinoMain.cpp b/tests/host/common/ArduinoMain.cpp new file mode 100644 index 0000000000..3a3dcb4e8b --- /dev/null +++ b/tests/host/common/ArduinoMain.cpp @@ -0,0 +1,16 @@ + +#include + +#include // usleep + +int main (void) +{ + setup(); + while (true) + { + usleep(10000); // not 100% cpu + loop(); + } + return 0; +} + diff --git a/tests/host/common/HardwareSerial.cpp b/tests/host/common/HardwareSerial.cpp new file mode 100644 index 0000000000..81d45cd65f --- /dev/null +++ b/tests/host/common/HardwareSerial.cpp @@ -0,0 +1,66 @@ + +#include + +#include // 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); +} + +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; + putchar(c); + return 1; +} + +int uart_peek_char(uart_t* uart) +{ + ///XXXTODO + (void)uart; + return -1; +} + +int uart_read_char(uart_t* uart) +{ + ///XXXTODO + (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" diff --git a/tests/host/common/WMath.cpp b/tests/host/common/WMath.cpp index d564ea8e97..4201b20ead 100644 --- a/tests/host/common/WMath.cpp +++ b/tests/host/common/WMath.cpp @@ -52,10 +52,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; } diff --git a/tests/host/core-mock/machine/ansi.h b/tests/host/common/machine/ansi.h similarity index 100% rename from tests/host/core-mock/machine/ansi.h rename to tests/host/common/machine/ansi.h diff --git a/tests/host/core-mock/mock.h b/tests/host/common/mock.h similarity index 88% rename from tests/host/core-mock/mock.h rename to tests/host/common/mock.h index 5e741d6a26..8843d7ccba 100644 --- a/tests/host/core-mock/mock.h +++ b/tests/host/common/mock.h @@ -1,9 +1,16 @@ // include host's STL before any other include file // because core definition like max() is in the way + #include // exotic typedefs used in the sdk + #include typedef uint8_t uint8; typedef uint32_t uint32; + +// + +#include + diff --git a/tests/host/core-mock/queue.h b/tests/host/common/queue.h similarity index 100% rename from tests/host/core-mock/queue.h rename to tests/host/common/queue.h diff --git a/tests/host/core-mock/user_interface.h b/tests/host/common/user_interface.h similarity index 100% rename from tests/host/core-mock/user_interface.h rename to tests/host/common/user_interface.h From 6b5c63438b391ff9b974e65800a7f9f6463f2b86 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Fri, 9 Nov 2018 19:49:05 +0100 Subject: [PATCH 03/50] WIP --- libraries/ESP8266WiFi/src/WiFiClient.cpp | 2 +- tests/host/Makefile | 55 ++++++++--- tests/host/common/c_types.h | 115 +++++++++++++++++++++++ tests/host/common/mock.h | 2 + tests/host/common/user_interface.cpp | 52 ++++++++++ tests/host/common/user_interface.h | 3 - 6 files changed, 213 insertions(+), 16 deletions(-) create mode 100644 tests/host/common/c_types.h create mode 100644 tests/host/common/user_interface.cpp delete mode 100644 tests/host/common/user_interface.h diff --git a/libraries/ESP8266WiFi/src/WiFiClient.cpp b/libraries/ESP8266WiFi/src/WiFiClient.cpp index 6bb79a4a9b..9ba168e742 100644 --- a/libraries/ESP8266WiFi/src/WiFiClient.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClient.cpp @@ -38,7 +38,7 @@ extern "C" #include "lwip/tcp.h" #include "lwip/inet.h" #include "lwip/netif.h" -#include "include/ClientContext.h" +#include #include "c_types.h" uint16_t WiFiClient::_localPort = 0; diff --git a/tests/host/Makefile b/tests/host/Makefile index 15dc68d7e2..504d2db51d 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -2,12 +2,6 @@ BINARY_DIRECTORY := bin LCOV_DIRECTORY := lcov OUTPUT_BINARY := $(BINARY_DIRECTORY)/host_tests CORE_PATH := ../../cores/esp8266 -OPT := -O0 - -INC_PATHS += $(addprefix -I,\ - $(shell echo ../../libraries/*/src) \ - $(shell echo ../../libraries/*) \ -) # I wasn't able to build with clang when -coverage flag is enabled, forcing GCC on OS X ifeq ($(shell uname -s),Darwin) @@ -52,6 +46,7 @@ MOCK_CPP_FILES := $(MOCK_CPP_FILES_COMMON) $(addprefix common/,\ MOCK_CPP_FILES_EMU := $(MOCK_CPP_FILES_COMMON) $(addprefix common/,\ ArduinoMain.cpp \ + user_interface.cpp \ ) MOCK_C_FILES := $(addprefix common/,\ @@ -59,18 +54,29 @@ MOCK_C_FILES := $(addprefix common/,\ noniso.c \ ) -INC_PATHS += $(addprefix -I, \ +INC_PATHS := $(addprefix -I,\ common \ $(CORE_PATH) \ + $(shell echo ../../libraries/*/src) \ + $(shell echo ../../libraries/*) \ ../../tools/sdk/include \ ) +INC_PATHS += -DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 \ + $(addprefix -I,\ + ../../tools/sdk/lwip2/include \ + ) + TEST_CPP_FILES := \ fs/test_fs.cpp \ core/test_pgmspace.cpp \ core/test_md5builder.cpp \ core/test_string.cpp +PREINCLUDES := \ + -include common/mock.h \ + -include common/c_types.h \ + CXXFLAGS += -std=c++11 -Wall -Werror -coverage -O0 -fno-common -g CFLAGS += -std=c99 -Wall -Werror -coverage -O0 -fno-common -g LDFLAGS += -coverage -O0 @@ -96,7 +102,7 @@ test: $(OUTPUT_BINARY) $(OUTPUT_BINARY) clean: clean-objects clean-coverage - rm -rf $(BINARY_DIRECTORY) + rm -rf $(BINARY_DIRECTORY) examples clean-objects: rm -rf $(OBJECTS) @@ -129,11 +135,11 @@ $(BINARY_DIRECTORY): #$(C_OBJECTS): %.c.o: %.c %.c.o: %.c - $(CC) $(CFLAGS) $(INC_PATHS) -c -o $@ $< + $(CC) $(PREINCLUDES) $(CFLAGS) $(INC_PATHS) -c -o $@ $< #$(CPP_OBJECTS): %.cpp.o: %.cpp %.cpp.o: %.cpp - $(CXX) -include common/mock.h $(CXXFLAGS) $(INC_PATHS) -c -o $@ $< + $(CXX) $(PREINCLUDES) $(CXXFLAGS) $(INC_PATHS) -c -o $@ $< $(BINARY_DIRECTORY)/core.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE) ar -rcu $@ $(C_OBJECTS) $(CPP_OBJECTS_CORE) @@ -146,7 +152,32 @@ $(OUTPUT_BINARY): $(BINARY_DIRECTORY) $(CPP_OBJECTS_TESTS) $(BINARY_DIRECTORY)/c # building ino sources -include examples/Makefile.inc.ino -CPP_OBJECTS_CORE_EMU = $(MOCK_CPP_FILES_EMU:.cpp=.cpp.o) $(CORE_CPP_FILES:.cpp=.cpp.o) +MOCK_ARDUINO_LIBS := $(addprefix ../../libraries/ESP8266WiFi/src/,\ + ESP8266WiFi.cpp \ + ESP8266WiFiAP.cpp \ + ESP8266WiFiGeneric.cpp \ + ESP8266WiFiMulti.cpp \ + ESP8266WiFiSTA-WPS.cpp \ + ESP8266WiFiSTA.cpp \ + ESP8266WiFiScan.cpp \ + WiFiServer.cpp \ + WiFiClient.cpp \ +) +# WiFiUdp.cpp \ + +MOCK_ARDUINO_LIBS += $(addprefix ../../libraries/ESP8266WiFi/src/,\ +) + +MOCK_ARDUINO_LIBS += $(addprefix $(CORE_PATH)/,\ + IPAddress.cpp \ +) + +CPP_OBJECTS_CORE_EMU_SOURCE = \ + $(MOCK_CPP_FILES_EMU) \ + $(CORE_CPP_FILES) \ + $(MOCK_ARDUINO_LIBS) \ + +CPP_OBJECTS_CORE_EMU = $(CPP_OBJECTS_CORE_EMU_SOURCE:.cpp=.cpp.o) common/fullcore.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE_EMU) ar -rcu $@ $^ @@ -156,7 +187,7 @@ common/fullcore.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE_EMU) $(CXX) $(LDFLAGS) $^ -o $@ %.ino-host.o: %.ino-host.cpp - $(CXX) -include common/mock.h $(CXXFLAGS) $(INC_PATHS) -c -o $@ $< + $(CXX) $(PREINCLUDES) $(CXXFLAGS) $(INC_PATHS) -c -o $@ $< .PRECIOUS: %-host.cpp %.ino-host.cpp: %.ino diff --git a/tests/host/common/c_types.h b/tests/host/common/c_types.h new file mode 100644 index 0000000000..765e307a95 --- /dev/null +++ b/tests/host/common/c_types.h @@ -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 + * + * 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 +#include +#include +#include + +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_ */ diff --git a/tests/host/common/mock.h b/tests/host/common/mock.h index 8843d7ccba..d3f99536b1 100644 --- a/tests/host/common/mock.h +++ b/tests/host/common/mock.h @@ -2,7 +2,9 @@ // include host's STL before any other include file // because core definition like max() is in the way +#ifdef __cplusplus #include +#endif // exotic typedefs used in the sdk diff --git a/tests/host/common/user_interface.cpp b/tests/host/common/user_interface.cpp new file mode 100644 index 0000000000..77ae87de9a --- /dev/null +++ b/tests/host/common/user_interface.cpp @@ -0,0 +1,52 @@ + +extern "C" +{ + +#include + +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; +} + + + +} // extern "C" diff --git a/tests/host/common/user_interface.h b/tests/host/common/user_interface.h deleted file mode 100644 index 758fe9e512..0000000000 --- a/tests/host/common/user_interface.h +++ /dev/null @@ -1,3 +0,0 @@ - -// mock user_interface.h - From 786aa81ff289f491eb1baf22178f35e0e010af3e Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Fri, 9 Nov 2018 19:50:11 +0100 Subject: [PATCH 04/50] WIP --- tests/host/common/include/ClientContext.h | 223 ++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 tests/host/common/include/ClientContext.h diff --git a/tests/host/common/include/ClientContext.h b/tests/host/common/include/ClientContext.h new file mode 100644 index 0000000000..b7c3e5d2bc --- /dev/null +++ b/tests/host/common/include/ClientContext.h @@ -0,0 +1,223 @@ +/* + */ +#ifndef CLIENTCONTEXT_H +#define CLIENTCONTEXT_H + +class ClientContext; +class WiFiClient; + +extern "C" void esp_yield(); +extern "C" void esp_schedule(); + +#include + +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()) + { + } + + err_t abort() + { + return ERR_ABRT; + } + + err_t close() + { + err_t err = ERR_OK; +// err = ERR_ABRT; + return err; + } + + ~ClientContext() + { + } + + 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 0; + } + + size_t availableForWrite() + { + return 0; + } + + void setNoDelay(bool nodelay) + { + } + + bool getNoDelay() const + { + return false; + } + + void setTimeout(int timeout_ms) + { + } + + int getTimeout() const + { + return 0; + } + + uint32_t getRemoteAddress() const + { + return 0; + } + + uint16_t getRemotePort() const + { + return 0; + } + + uint32_t getLocalAddress() const + { + return 0; + } + + uint16_t getLocalPort() const + { + return 0; + } + + size_t getSize() const + { + return 0; + } + + char read() + { + return -1; + } + + size_t read(char* dst, size_t size) + { + return 0; + } + + char peek() const + { + return -1; + } + + size_t peekBytes(char *dst, size_t size) const + { + return 0; + } + + void discard_received() + { + } + + bool wait_until_sent(int max_wait_ms = WIFICLIENT_MAX_FLUSH_WAIT_MS) + { + return true; + } + + uint8_t state() const + { + return 0; + } + + size_t write(const uint8_t* data, size_t size) + { + return 0; + } + + size_t write(Stream& stream) + { + return 0; + } + + size_t write_P(PGM_P buf, size_t size) + { + return 0; + } + + 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) + { + } + + bool isKeepAliveEnabled () const + { + return false; + } + + uint16_t getKeepAliveIdle () const + { + return 0; + } + + uint16_t getKeepAliveInterval () const + { + return 0; + } + + uint8_t getKeepAliveCount () const + { + return 0; + } + + bool getSync () const + { + return _sync; + } + + void setSync (bool sync) + { + _sync = sync; + } + +private: + + discard_cb_t _discard_cb; + void* _discard_cb_arg; + + DataSource* _datasource = nullptr; + + int8_t _refcnt; + ClientContext* _next; + + bool _sync; +}; + +#endif//CLIENTCONTEXT_H From 780e9d90b3729878e237b0b256ee97e0a6034548 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Sat, 10 Nov 2018 02:08:50 +0100 Subject: [PATCH 05/50] WIP --- tests/host/Makefile | 7 +- tests/host/common/Arduino.cpp | 2 + tests/host/common/HardwareSerial.cpp | 2 +- tests/host/common/mock.h | 2 + tests/host/common/user_interface.cpp | 247 +++++++++++++++++++++++++++ 5 files changed, 256 insertions(+), 4 deletions(-) diff --git a/tests/host/Makefile b/tests/host/Makefile index 504d2db51d..9a5b39ed28 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -165,10 +165,10 @@ MOCK_ARDUINO_LIBS := $(addprefix ../../libraries/ESP8266WiFi/src/,\ ) # WiFiUdp.cpp \ -MOCK_ARDUINO_LIBS += $(addprefix ../../libraries/ESP8266WiFi/src/,\ -) +MOCK_ARDUINO_LIBS += \ + common/MockClientContext.cpp \ -MOCK_ARDUINO_LIBS += $(addprefix $(CORE_PATH)/,\ +ARDUINO_LIBS += $(addprefix $(CORE_PATH)/,\ IPAddress.cpp \ ) @@ -176,6 +176,7 @@ CPP_OBJECTS_CORE_EMU_SOURCE = \ $(MOCK_CPP_FILES_EMU) \ $(CORE_CPP_FILES) \ $(MOCK_ARDUINO_LIBS) \ + $(ARDUINO_LIBS) \ CPP_OBJECTS_CORE_EMU = $(CPP_OBJECTS_CORE_EMU_SOURCE:.cpp=.cpp.o) diff --git a/tests/host/common/Arduino.cpp b/tests/host/common/Arduino.cpp index e3d6eccefc..9c8fa59680 100644 --- a/tests/host/common/Arduino.cpp +++ b/tests/host/common/Arduino.cpp @@ -16,6 +16,7 @@ #include #include "Arduino.h" +#include extern "C" unsigned long millis() { @@ -36,4 +37,5 @@ extern "C" void __panic_func(const char* file, int line, const char* func) { extern "C" void delay(unsigned long ms) { + usleep(ms * 1000); } diff --git a/tests/host/common/HardwareSerial.cpp b/tests/host/common/HardwareSerial.cpp index 81d45cd65f..e554a66d33 100644 --- a/tests/host/common/HardwareSerial.cpp +++ b/tests/host/common/HardwareSerial.cpp @@ -38,7 +38,7 @@ size_t uart_write_char(uart_t* uart, char c) { //XXXTODO (void)uart; - putchar(c); + write(1, &c, 1); return 1; } diff --git a/tests/host/common/mock.h b/tests/host/common/mock.h index d3f99536b1..cd6a290294 100644 --- a/tests/host/common/mock.h +++ b/tests/host/common/mock.h @@ -16,3 +16,5 @@ typedef uint32_t uint32; #include +#define lwip_htons htons +#define lwip_htonl htonl diff --git a/tests/host/common/user_interface.cpp b/tests/host/common/user_interface.cpp index 77ae87de9a..814e873219 100644 --- a/tests/host/common/user_interface.cpp +++ b/tests/host/common/user_interface.cpp @@ -1,4 +1,6 @@ +#include + extern "C" { @@ -47,6 +49,251 @@ bool wifi_station_get_config (struct station_config *config) 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; +} + +bool wifi_get_ip_info (uint8 if_index, struct ip_info *info) +{ + //XXXTODO + if (if_index != STATION_IF) + fprintf(stderr, "we are not AP"); + + //XXXTODO (give ip address of default route's interface?) + info->ip.addr = htonl(0x7f000001); + info->netmask.addr = htonl(0xff000000); + info->gw.addr = htonl(0x7f000001); + + 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; +} + +/////////////////////////////////////// +// 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 +bool smartconfig_start (sc_callback_t cb, ...) +{ + //XXXFIXME ... -> ptr + cb(SC_STATUS_LINK, NULL); + return true; +} + +bool smartconfig_stop (void) +{ + return true; +} + + } // extern "C" From b4e9cfb142cfe68e1243afa5dcaf15a816beb14d Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Sat, 10 Nov 2018 02:18:43 +0100 Subject: [PATCH 06/50] WIP --- tests/host/common/HardwareSerial.cpp | 29 +++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/tests/host/common/HardwareSerial.cpp b/tests/host/common/HardwareSerial.cpp index e554a66d33..8a20caa684 100644 --- a/tests/host/common/HardwareSerial.cpp +++ b/tests/host/common/HardwareSerial.cpp @@ -11,19 +11,19 @@ HardwareSerial::HardwareSerial (int uart_nr) fprintf(stderr, MOCK "FIXME HardwareSerial::HardwareSerial(%d)\n", uart_nr); } -void HardwareSerial::begin(unsigned long baud, SerialConfig config, SerialMode mode, uint8_t tx_pin) +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); } -int HardwareSerial::available(void) +int HardwareSerial::available (void) { printf(MOCK "TODO HardwareSerial::available\n"); return 0; } -void HardwareSerial::flush() +void HardwareSerial::flush () { //XXXTODO fflush(stdout); @@ -34,29 +34,40 @@ void HardwareSerial::flush() extern "C" { -size_t uart_write_char(uart_t* uart, char c) +size_t uart_write_char (uart_t* uart, char c) { //XXXTODO (void)uart; - write(1, &c, 1); - return 1; + return write(1, &c, 1); } -int uart_peek_char(uart_t* uart) +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) +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) +size_t uart_write (uart_t* uart, const char* buf, size_t size) { ///XXXTODO (void)uart; From b087d700de5984086c01ea501ced24b1844a4b86 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Sat, 10 Nov 2018 03:45:47 +0100 Subject: [PATCH 07/50] WIP --- tests/host/Makefile | 1 + tests/host/common/MockClientContext.cpp | 27 +++++++ tests/host/common/MockClientContextSocket.cpp | 72 +++++++++++++++++++ tests/host/common/include/ClientContext.h | 58 +++++++++++---- tests/host/common/mock.h | 5 ++ 5 files changed, 151 insertions(+), 12 deletions(-) create mode 100644 tests/host/common/MockClientContext.cpp create mode 100644 tests/host/common/MockClientContextSocket.cpp diff --git a/tests/host/Makefile b/tests/host/Makefile index 9a5b39ed28..a3152cfca7 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -167,6 +167,7 @@ MOCK_ARDUINO_LIBS := $(addprefix ../../libraries/ESP8266WiFi/src/,\ MOCK_ARDUINO_LIBS += \ common/MockClientContext.cpp \ + common/MockClientContextSocket.cpp \ ARDUINO_LIBS += $(addprefix $(CORE_PATH)/,\ IPAddress.cpp \ diff --git a/tests/host/common/MockClientContext.cpp b/tests/host/common/MockClientContext.cpp new file mode 100644 index 0000000000..47463218e7 --- /dev/null +++ b/tests/host/common/MockClientContext.cpp @@ -0,0 +1,27 @@ + +#include +#include +#include +#include +#include + +#include // 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; +} diff --git a/tests/host/common/MockClientContextSocket.cpp b/tests/host/common/MockClientContextSocket.cpp new file mode 100644 index 0000000000..7527c1d2e7 --- /dev/null +++ b/tests/host/common/MockClientContextSocket.cpp @@ -0,0 +1,72 @@ + +// separated from lwIP to avoid type conflicts + +#include +#include +#include +#include +#include +#include + +int mockConnect (uint32_t addr, int& sock, int port) +{ + struct sockaddr_in server; + if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) == -1) + { + perror(MOCK "ClientContext:connect: ::socket()"); + return 0; + exit(EXIT_FAILURE); + } + server.sin_family = AF_INET; + server.sin_port = htons(port); + memcpy(&server.sin_addr, &addr, 4); + if (::connect(sock, (struct sockaddr*)&server, sizeof(server)) == -1) + { + perror(MOCK "ClientContext::connect: ::connect()"); + return 0; + } + +//XXXFIXME NONBLOCK! + + return 1; +} + +size_t mockReadReady (int sock) +{ + struct pollfd p; + p.fd = sock; + p.events = POLLIN; + return poll(&p, 1, 0); +} + +size_t mockRead (int sock, char* dst, size_t size, int timeout_ms) +{ + struct pollfd p; + p.fd = sock; + p.events = POLLIN; + int ret = poll(&p, 1, timeout_ms); + if (ret == -1) + { + fprintf(stderr, MOCK "ClientContext::read: poll(%d): %s\n", sock, strerror(errno)); + return 0; + } + if (ret) + ret = ::read(sock, dst, size); + return ret; +} + +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); + return ret; +} diff --git a/tests/host/common/include/ClientContext.h b/tests/host/common/include/ClientContext.h index b7c3e5d2bc..4b84a8dac4 100644 --- a/tests/host/common/include/ClientContext.h +++ b/tests/host/common/include/ClientContext.h @@ -22,22 +22,26 @@ class ClientContext _discard_cb(discard_cb), _discard_cb_arg(discard_cb_arg), _refcnt(0), _next(0), _sync(::getDefaultPrivateGlobalSyncValue()) { + (void)pcb; + _sock = -1; } err_t abort() { + if (_sock >= 0) + ::close(_sock); return ERR_ABRT; } err_t close() { - err_t err = ERR_OK; -// err = ERR_ABRT; - return err; + abort(); + return ERR_OK; } ~ClientContext() { + abort(); } ClientContext* next() const @@ -73,74 +77,91 @@ class ClientContext int connect(ip_addr_t* addr, uint16_t port) { - return 0; + return mockConnect(addr->addr, _sock, port); } size_t availableForWrite() { - return 0; + // 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 0; + 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() const { - return 0; + return mockReadReady(_sock)? 16: 0; //XXXFIXMEDIRTYBUFFERIZE! } char read() { - return -1; + char c; + if (read(&c, 1)) + return c; + return 0; } - size_t read(char* dst, size_t size) + size_t read (char* dst, size_t size) { - return 0; + return mockRead(_sock, dst, size, _timeout_ms); } char peek() const { + // mock implementation will be more complex because of this + fprintf(stderr, MOCK "ClientContext::peek !\n"); + ::abort(); return -1; } size_t peekBytes(char *dst, size_t size) const { + // mock implementation will be more complex because of this + fprintf(stderr, MOCK "ClientContext::peek !\n"); + ::abort(); return 0; } @@ -160,50 +181,58 @@ class ClientContext size_t write(const uint8_t* data, size_t size) { - return 0; + return mockWrite(_sock, data, size, _timeout_ms); } size_t write(Stream& stream) { + fprintf(stderr, MOCK "TODO ClientContext::write(Stream)\n"); return 0; } size_t write_P(PGM_P buf, size_t size) { - return 0; + 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; } @@ -218,6 +247,11 @@ class ClientContext ClientContext* _next; bool _sync; + + // MOCK + + int _sock = -1; + int _timeout_ms = 5000; }; #endif//CLIENTCONTEXT_H diff --git a/tests/host/common/mock.h b/tests/host/common/mock.h index cd6a290294..d8833e643e 100644 --- a/tests/host/common/mock.h +++ b/tests/host/common/mock.h @@ -18,3 +18,8 @@ typedef uint32_t uint32; #define lwip_htons htons #define lwip_htonl htonl + +int mockConnect (uint32_t addr, int& sock, int port); +size_t mockReadReady (int sock); +size_t mockRead (int sock, char* dst, size_t size, int timeout_ms); +size_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms); From 3ac0bf140637b146126cbebcfe6a7deaa5479f9d Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Sat, 10 Nov 2018 21:38:56 +0100 Subject: [PATCH 08/50] WIP --- tests/host/common/MockClientContextSocket.cpp | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/tests/host/common/MockClientContextSocket.cpp b/tests/host/common/MockClientContextSocket.cpp index 7527c1d2e7..35c9ff553f 100644 --- a/tests/host/common/MockClientContextSocket.cpp +++ b/tests/host/common/MockClientContextSocket.cpp @@ -6,27 +6,32 @@ #include #include #include +#include #include -int mockConnect (uint32_t addr, int& sock, int port) +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; - exit(EXIT_FAILURE); } server.sin_family = AF_INET; server.sin_port = htons(port); - memcpy(&server.sin_addr, &addr, 4); + memcpy(&server.sin_addr, &ipv4, 4); if (::connect(sock, (struct sockaddr*)&server, sizeof(server)) == -1) { perror(MOCK "ClientContext::connect: ::connect()"); return 0; } -//XXXFIXME NONBLOCK! + 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; } @@ -36,7 +41,7 @@ size_t mockReadReady (int sock) struct pollfd p; p.fd = sock; p.events = POLLIN; - return poll(&p, 1, 0); + return poll(&p, 1, 0) && !!(p.revents & POLLIN); } size_t mockRead (int sock, char* dst, size_t size, int timeout_ms) @@ -51,7 +56,14 @@ size_t mockRead (int sock, char* dst, size_t size, int timeout_ms) return 0; } if (ret) + { ret = ::read(sock, dst, size); + if (ret == -1) + { + fprintf(stderr, MOCK "ClientContext::read: read(%d): %s\n", sock, strerror(errno)); + return 0; + } + } return ret; } @@ -67,6 +79,13 @@ size_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms) 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; + } + } return ret; } From 1d795e54dbd8064969bc344b741620dfbd7a572e Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Sat, 10 Nov 2018 23:37:57 +0100 Subject: [PATCH 09/50] WIP bufferize tcp input --- tests/host/common/MockClientContextSocket.cpp | 73 +++++++++++++------ tests/host/common/include/ClientContext.h | 41 +++++++---- tests/host/common/mock.h | 14 +++- 3 files changed, 85 insertions(+), 43 deletions(-) diff --git a/tests/host/common/MockClientContextSocket.cpp b/tests/host/common/MockClientContextSocket.cpp index 35c9ff553f..500587f0c0 100644 --- a/tests/host/common/MockClientContextSocket.cpp +++ b/tests/host/common/MockClientContextSocket.cpp @@ -36,37 +36,62 @@ int mockConnect (uint32_t ipv4, int& sock, int port) return 1; } -size_t mockReadReady (int sock) +size_t mockFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize) { - struct pollfd p; - p.fd = sock; - p.events = POLLIN; - return poll(&p, 1, 0) && !!(p.revents & POLLIN); + 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 %d bytes: %s\n", (int)maxread, strerror(errno)); + ret = 0; + } + return ccinbufsize += ret; } -size_t mockRead (int sock, char* dst, size_t size, int timeout_ms) +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 %d bytes (-> %d)\n", CCBUFSIZE, (int)usersize - CCBUFSIZE, (int)usersize); + struct pollfd p; - p.fd = sock; - p.events = POLLIN; - int ret = poll(&p, 1, timeout_ms); - if (ret == -1) - { - fprintf(stderr, MOCK "ClientContext::read: poll(%d): %s\n", sock, strerror(errno)); - return 0; - } - if (ret) - { - ret = ::read(sock, dst, size); - if (ret == -1) - { - fprintf(stderr, MOCK "ClientContext::read: read(%d): %s\n", sock, strerror(errno)); - return 0; - } - } - return ret; + 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; diff --git a/tests/host/common/include/ClientContext.h b/tests/host/common/include/ClientContext.h index 4b84a8dac4..8001ee5b54 100644 --- a/tests/host/common/include/ClientContext.h +++ b/tests/host/common/include/ClientContext.h @@ -131,9 +131,9 @@ class ClientContext return 0; } - size_t getSize() const + size_t getSize() { - return mockReadReady(_sock)? 16: 0; //XXXFIXMEDIRTYBUFFERIZE! + return _inbufsize?: mockFillInBuf(_sock, _inbuf, _inbufsize); } char read() @@ -146,23 +146,20 @@ class ClientContext size_t read (char* dst, size_t size) { - return mockRead(_sock, dst, size, _timeout_ms); + return mockRead(_sock, dst, size, _timeout_ms, _inbuf, _inbufsize); } - char peek() const + int peek() { - // mock implementation will be more complex because of this - fprintf(stderr, MOCK "ClientContext::peek !\n"); - ::abort(); - return -1; + char c; + if (!mockPeekBytes(_sock, &c, 1, _timeout_ms, _inbuf, _inbufsize)) + return -1; + return c; } - size_t peekBytes(char *dst, size_t size) const + size_t peekBytes(char *dst, size_t size) { - // mock implementation will be more complex because of this - fprintf(stderr, MOCK "ClientContext::peek !\n"); - ::abort(); - return 0; + return mockPeekBytes(_sock, dst, size, _timeout_ms, _inbuf, _inbufsize); } void discard_received() @@ -186,8 +183,19 @@ class ClientContext size_t write(Stream& stream) { - fprintf(stderr, MOCK "TODO ClientContext::write(Stream)\n"); - return 0; + 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) @@ -252,6 +260,9 @@ class ClientContext int _sock = -1; int _timeout_ms = 5000; + + char _inbuf [CCBUFSIZE]; + size_t _inbufsize = 0; }; #endif//CLIENTCONTEXT_H diff --git a/tests/host/common/mock.h b/tests/host/common/mock.h index d8833e643e..764af15739 100644 --- a/tests/host/common/mock.h +++ b/tests/host/common/mock.h @@ -19,7 +19,13 @@ typedef uint32_t uint32; #define lwip_htons htons #define lwip_htonl htonl -int mockConnect (uint32_t addr, int& sock, int port); -size_t mockReadReady (int sock); -size_t mockRead (int sock, char* dst, size_t size, int timeout_ms); -size_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms); +#ifdef __cplusplus +#ifndef CCBUFSIZE +#define CCBUFSIZE 512 +#endif +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); +#endif From c9d302ad436bcb4a9802f64624daff212da25df6 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Sun, 11 Nov 2018 03:09:35 +0100 Subject: [PATCH 10/50] WIP Makefile --- tests/host/Makefile | 61 ++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/tests/host/Makefile b/tests/host/Makefile index a3152cfca7..2ba776556f 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -1,6 +1,6 @@ -BINARY_DIRECTORY := bin +BINDIR := bin LCOV_DIRECTORY := lcov -OUTPUT_BINARY := $(BINARY_DIRECTORY)/host_tests +OUTPUT_BINARY := $(BINDIR)/host_tests CORE_PATH := ../../cores/esp8266 # I wasn't able to build with clang when -coverage flag is enabled, forcing GCC on OS X @@ -13,6 +13,8 @@ VALGRIND ?= valgrind LCOV ?= lcov GENHTML ?= genhtml +$(shell mkdir -p $(BINDIR)) + CORE_CPP_FILES := $(addprefix $(CORE_PATH)/,\ StreamString.cpp \ Stream.cpp \ @@ -102,10 +104,10 @@ test: $(OUTPUT_BINARY) $(OUTPUT_BINARY) clean: clean-objects clean-coverage - rm -rf $(BINARY_DIRECTORY) examples + rm -rf $(BINDIR) clean-objects: - rm -rf $(OBJECTS) + rm -rf $(OBJECTS) $(CPP_OBJECTS_CORE_EMU) clean-coverage: rm -rf $(COVERAGE_FILES) $(LCOV_DIRECTORY) *.gcov @@ -130,27 +132,23 @@ build-info: $(GCOV) -v @echo "----------------------------------" -$(BINARY_DIRECTORY): - mkdir -p $@ +-include $(BINDIR)/.*.d -#$(C_OBJECTS): %.c.o: %.c %.c.o: %.c - $(CC) $(PREINCLUDES) $(CFLAGS) $(INC_PATHS) -c -o $@ $< + $(CC) $(PREINCLUDES) $(CFLAGS) $(INC_PATHS) -MD -MF $(BINDIR)/.$(notdir $<).d -c -o $@ $< -#$(CPP_OBJECTS): %.cpp.o: %.cpp %.cpp.o: %.cpp - $(CXX) $(PREINCLUDES) $(CXXFLAGS) $(INC_PATHS) -c -o $@ $< + $(CXX) $(PREINCLUDES) $(CXXFLAGS) $(INC_PATHS) -MD -MF $(BINDIR)/.$(notdir $<).d -c -o $@ $< -$(BINARY_DIRECTORY)/core.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE) +$(BINDIR)/core.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE) ar -rcu $@ $(C_OBJECTS) $(CPP_OBJECTS_CORE) 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 + $(CXX) $(LDFLAGS) $(CPP_OBJECTS_TESTS) $(BINDIR)/core.a $(LIBS) -o $@ ################################################# # building ino sources --include examples/Makefile.inc.ino MOCK_ARDUINO_LIBS := $(addprefix ../../libraries/ESP8266WiFi/src/,\ ESP8266WiFi.cpp \ @@ -173,48 +171,43 @@ ARDUINO_LIBS += $(addprefix $(CORE_PATH)/,\ IPAddress.cpp \ ) -CPP_OBJECTS_CORE_EMU_SOURCE = \ +CPP_SOURCES_CORE_EMU = \ $(MOCK_CPP_FILES_EMU) \ $(CORE_CPP_FILES) \ $(MOCK_ARDUINO_LIBS) \ $(ARDUINO_LIBS) \ -CPP_OBJECTS_CORE_EMU = $(CPP_OBJECTS_CORE_EMU_SOURCE:.cpp=.cpp.o) +CPP_OBJECTS_CORE_EMU = $(CPP_SOURCES_CORE_EMU:.cpp=.cpp.o) common/fullcore.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE_EMU) ar -rcu $@ $^ ranlib -c $@ -%.ino-host: %.ino-host.o common/fullcore.a - $(CXX) $(LDFLAGS) $^ -o $@ - -%.ino-host.o: %.ino-host.cpp - $(CXX) $(PREINCLUDES) $(CXXFLAGS) $(INC_PATHS) -c -o $@ $< +.PRECIOUS: %.cpp.o +%: %.cpp.o common/fullcore.a + $(CXX) $(LDFLAGS) $< common/fullcore.a -o $@ + ln -s ../$@ $(BINDIR) -.PRECIOUS: %-host.cpp -%.ino-host.cpp: %.ino +.PRECIOUS: %.cpp +%.cpp: %.ino cp $< $@ ################################################# # Makefile.inc.ino generation +-include $(BINDIR)/Makefile.inc.ino -.PHONY: examples - -# default "examples" rule (overridden in Makefile.inc.ino when built) -examples: +$(BINDIR)/Makefile.inc.ino: # copy examples locally - rm -f Makefile.inc.ino all=""; \ - for dir in ../../libraries/*/$@; do \ + for dir in ../../libraries/*/examples; do \ exampledir=$${dir%/*}; \ exampledirname=$${exampledir##*/}; \ for subdir in $$dir/*; do \ exname=$${subdir##*/}; \ - mkdir -p $@/$$exampledirname/$$exname; \ - (cd $$subdir && tar cf - .) | (cd $@/$$exampledirname/$$exname; tar xf -); \ - echo $@/$$exampledirname/$$exname/$$exname-host: $@/$$exampledirname/$$exname/$$exname.ino >> $@/Makefile.inc.ino; \ - all="$$all $@/$$exampledirname/$$exname/$$exname.ino-host"; \ + all="$$all $$subdir/$$exname"; \ done; \ done; \ - echo "$@: $$all" >> $@/Makefile.inc.ino + echo "examples: $$all" > $@ + +examples: $(BINDIR)/Makefile.inc.ino $(MAKE) $@ From b1e57697427bfc2d341d263d92031d79572362ea Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Mon, 12 Nov 2018 02:30:19 +0100 Subject: [PATCH 11/50] WIP --- .../ESP8266WebServer/src/ESP8266WebServer.cpp | 4 +- tests/host/Makefile | 26 +++--- tests/host/common/ArduinoWire.cpp | 26 ++++++ tests/host/common/MockWiFiServer.cpp | 30 +++++++ tests/host/common/MockWiFiServerSocket.cpp | 81 +++++++++++++++++++ tests/host/common/include/ClientContext.h | 23 +++--- tests/host/common/mock.h | 7 ++ 7 files changed, 176 insertions(+), 21 deletions(-) create mode 100644 tests/host/common/ArduinoWire.cpp create mode 100644 tests/host/common/MockWiFiServer.cpp create mode 100644 tests/host/common/MockWiFiServerSocket.cpp diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp index aec3f732d6..1435a463ae 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp @@ -440,7 +440,7 @@ void ESP8266WebServer::sendContent(const String& content) { if(_chunked) { char * chunkSize = (char *)malloc(11); if(chunkSize){ - sprintf(chunkSize, "%x%s", len, footer); + sprintf(chunkSize, "%x%s", (unsigned)len, footer); _currentClientWrite(chunkSize, strlen(chunkSize)); free(chunkSize); } @@ -463,7 +463,7 @@ void ESP8266WebServer::sendContent_P(PGM_P content, size_t size) { if(_chunked) { char * chunkSize = (char *)malloc(11); if(chunkSize){ - sprintf(chunkSize, "%x%s", size, footer); + sprintf(chunkSize, "%x%s", (unsigned)size, footer); _currentClientWrite(chunkSize, strlen(chunkSize)); free(chunkSize); } diff --git a/tests/host/Makefile b/tests/host/Makefile index 2ba776556f..3cde8a4636 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -133,6 +133,7 @@ build-info: @echo "----------------------------------" -include $(BINDIR)/.*.d +.SUFFIXES: %.c.o: %.c $(CC) $(PREINCLUDES) $(CFLAGS) $(INC_PATHS) -MD -MF $(BINDIR)/.$(notdir $<).d -c -o $@ $< @@ -150,7 +151,8 @@ $(OUTPUT_BINARY): $(CPP_OBJECTS_TESTS) $(BINDIR)/core.a ################################################# # building ino sources -MOCK_ARDUINO_LIBS := $(addprefix ../../libraries/ESP8266WiFi/src/,\ +MOCK_ARDUINO_LIBS := \ +$(addprefix ../../libraries/ESP8266WiFi/src/,\ ESP8266WiFi.cpp \ ESP8266WiFiAP.cpp \ ESP8266WiFiGeneric.cpp \ @@ -158,14 +160,20 @@ MOCK_ARDUINO_LIBS := $(addprefix ../../libraries/ESP8266WiFi/src/,\ ESP8266WiFiSTA-WPS.cpp \ ESP8266WiFiSTA.cpp \ ESP8266WiFiScan.cpp \ - WiFiServer.cpp \ WiFiClient.cpp \ -) -# WiFiUdp.cpp \ +) \ +$(addprefix ../../libraries/ESP8266WebServer/src/,\ + ESP8266WebServer.cpp \ + Parsing.cpp \ + detail/mimetable.cpp \ +) \ MOCK_ARDUINO_LIBS += \ - common/MockClientContext.cpp \ common/MockClientContextSocket.cpp \ + common/MockClientContext.cpp \ + common/MockWiFiServerSocket.cpp \ + common/MockWiFiServer.cpp \ + common/ArduinoWire.cpp \ ARDUINO_LIBS += $(addprefix $(CORE_PATH)/,\ IPAddress.cpp \ @@ -179,14 +187,14 @@ CPP_SOURCES_CORE_EMU = \ CPP_OBJECTS_CORE_EMU = $(CPP_SOURCES_CORE_EMU:.cpp=.cpp.o) -common/fullcore.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE_EMU) +bin/fullcore.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE_EMU) ar -rcu $@ $^ ranlib -c $@ .PRECIOUS: %.cpp.o -%: %.cpp.o common/fullcore.a - $(CXX) $(LDFLAGS) $< common/fullcore.a -o $@ - ln -s ../$@ $(BINDIR) +%: %.cpp.o bin/fullcore.a + $(CXX) $(LDFLAGS) $< bin/fullcore.a -o $@ + ln -sf ../$@ $(BINDIR) .PRECIOUS: %.cpp %.cpp: %.ino diff --git a/tests/host/common/ArduinoWire.cpp b/tests/host/common/ArduinoWire.cpp new file mode 100644 index 0000000000..be2e229f3b --- /dev/null +++ b/tests/host/common/ArduinoWire.cpp @@ -0,0 +1,26 @@ + +#include + +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); +} + diff --git a/tests/host/common/MockWiFiServer.cpp b/tests/host/common/MockWiFiServer.cpp new file mode 100644 index 0000000000..467d2380c8 --- /dev/null +++ b/tests/host/common/MockWiFiServer.cpp @@ -0,0 +1,30 @@ + +#include +#include + +#include +#include + +#include + +#define int2pcb(x) ((tcp_pcb*)(long)(x)) +#define pcb2int(x) ((int)(long)(x)) + +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(); +} diff --git a/tests/host/common/MockWiFiServerSocket.cpp b/tests/host/common/MockWiFiServerSocket.cpp new file mode 100644 index 0000000000..b20a6b878d --- /dev/null +++ b/tests/host/common/MockWiFiServerSocket.cpp @@ -0,0 +1,81 @@ + +#include + +#include +#include +#include +#include + +#define int2pcb(x) ((tcp_pcb*)(long)(x)) +#define pcb2int(x) ((int)(long)(x)) + +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 () +{ + 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, %d)\n", buf, (int)size); + return 0; +} diff --git a/tests/host/common/include/ClientContext.h b/tests/host/common/include/ClientContext.h index 8001ee5b54..34dce78652 100644 --- a/tests/host/common/include/ClientContext.h +++ b/tests/host/common/include/ClientContext.h @@ -25,11 +25,17 @@ class ClientContext (void)pcb; _sock = -1; } - + + ClientContext (int sock) + { + _sock = sock; + } + err_t abort() { if (_sock >= 0) ::close(_sock); + _sock = -1; return ERR_ABRT; } @@ -67,9 +73,8 @@ class ClientContext if(--_refcnt == 0) { discard_received(); close(); - if(_discard_cb) { - _discard_cb(_discard_cb_arg, this); - } + if (_discard_cb) + _discard_cb(_discard_cb_arg, this); DEBUGV(":del\r\n"); delete this; } @@ -173,7 +178,7 @@ class ClientContext uint8_t state() const { - return 0; + return _sock >= 0? ESTABLISHED: CLOSED; } size_t write(const uint8_t* data, size_t size) @@ -246,10 +251,8 @@ class ClientContext private: - discard_cb_t _discard_cb; - void* _discard_cb_arg; - - DataSource* _datasource = nullptr; + discard_cb_t _discard_cb = nullptr; + void* _discard_cb_arg = nullptr; int8_t _refcnt; ClientContext* _next; @@ -265,4 +268,4 @@ class ClientContext size_t _inbufsize = 0; }; -#endif//CLIENTCONTEXT_H +#endif //CLIENTCONTEXT_H diff --git a/tests/host/common/mock.h b/tests/host/common/mock.h index 764af15739..f9b92523ab 100644 --- a/tests/host/common/mock.h +++ b/tests/host/common/mock.h @@ -19,6 +19,11 @@ typedef uint32_t uint32; #define lwip_htons htons #define lwip_htonl htonl +#include +#define RANDOM_REG32 ((uint32_t)random()) + +// + #ifdef __cplusplus #ifndef CCBUFSIZE #define CCBUFSIZE 512 @@ -29,3 +34,5 @@ size_t mockPeekBytes (int sock, char* dst, size_t size, int timeout_ms, char* bu 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); #endif + +int serverAccept (int sock); From 83e4a434fc316a8b024b5bee7c8ec3c81eeec1a8 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Mon, 12 Nov 2018 18:49:17 +0100 Subject: [PATCH 12/50] WIP network to rework, tcp/udp to factorize, udp addresses broken --- tests/host/Makefile | 40 ++-- tests/host/common/MockClientContextSocket.cpp | 49 ++-- tests/host/common/MockTools.cpp | 15 ++ tests/host/common/MockUDPSocket.cpp | 133 +++++++++++ tests/host/common/MockWiFiServer.cpp | 13 ++ tests/host/common/MockWiFiServerSocket.cpp | 14 ++ tests/host/common/include/ClientContext.h | 21 +- tests/host/common/include/UdpContext.h | 212 ++++++++++++++++++ tests/host/common/mock.h | 27 ++- tests/host/common/user_interface.cpp | 8 +- 10 files changed, 475 insertions(+), 57 deletions(-) create mode 100644 tests/host/common/MockTools.cpp create mode 100644 tests/host/common/MockUDPSocket.cpp create mode 100644 tests/host/common/include/UdpContext.h diff --git a/tests/host/Makefile b/tests/host/Makefile index 3cde8a4636..4cebf82e2d 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -33,6 +33,7 @@ CORE_C_FILES := $(addprefix $(CORE_PATH)/,\ spiffs/spiffs_gc.c \ spiffs/spiffs_hydrogen.c \ spiffs/spiffs_nucleus.c \ + libb64/cencode.c \ ) MOCK_CPP_FILES_COMMON := $(addprefix common/,\ @@ -83,6 +84,8 @@ CXXFLAGS += -std=c++11 -Wall -Werror -coverage -O0 -fno-common -g CFLAGS += -std=c99 -Wall -Werror -coverage -O0 -fno-common -g LDFLAGS += -coverage -O0 VALGRINDFLAGS += --leak-check=full --track-origins=yes --error-limit=no --show-leak-kinds=all --error-exitcode=999 +# +CXXFLAGS += -Wno-nonnull-compare # libraries/ESP8266WiFi/src/include/UdpContext.h:85:9: error: nonnull argument ‘this’ compared to NULL [-Werror=nonnull-compare] -- (if(this != 0)) remduplicates = $(strip $(if $1,$(firstword $1) $(call remduplicates,$(filter-out $(firstword $1),$1)))) @@ -152,28 +155,35 @@ $(OUTPUT_BINARY): $(CPP_OBJECTS_TESTS) $(BINDIR)/core.a # building ino sources MOCK_ARDUINO_LIBS := \ -$(addprefix ../../libraries/ESP8266WiFi/src/,\ - ESP8266WiFi.cpp \ - ESP8266WiFiAP.cpp \ - ESP8266WiFiGeneric.cpp \ - ESP8266WiFiMulti.cpp \ - ESP8266WiFiSTA-WPS.cpp \ - ESP8266WiFiSTA.cpp \ - ESP8266WiFiScan.cpp \ - WiFiClient.cpp \ -) \ -$(addprefix ../../libraries/ESP8266WebServer/src/,\ - ESP8266WebServer.cpp \ - Parsing.cpp \ - detail/mimetable.cpp \ -) \ + $(addprefix ../../libraries/,\ + $(addprefix ESP8266WiFi/src/,\ + ESP8266WiFi.cpp \ + ESP8266WiFiAP.cpp \ + ESP8266WiFiGeneric.cpp \ + ESP8266WiFiMulti.cpp \ + ESP8266WiFiSTA-WPS.cpp \ + ESP8266WiFiSTA.cpp \ + ESP8266WiFiScan.cpp \ + WiFiClient.cpp \ + ) \ + $(addprefix ESP8266WebServer/src/,\ + ESP8266WebServer.cpp \ + Parsing.cpp \ + detail/mimetable.cpp \ + ) \ + ) + +# ESP8266mDNS/ESP8266mDNS.cpp \ + MOCK_ARDUINO_LIBS += \ common/MockClientContextSocket.cpp \ common/MockClientContext.cpp \ common/MockWiFiServerSocket.cpp \ common/MockWiFiServer.cpp \ + common/MockUDPSocket.cpp \ common/ArduinoWire.cpp \ + common/MockTools.cpp \ ARDUINO_LIBS += $(addprefix $(CORE_PATH)/,\ IPAddress.cpp \ diff --git a/tests/host/common/MockClientContextSocket.cpp b/tests/host/common/MockClientContextSocket.cpp index 500587f0c0..09e085ba41 100644 --- a/tests/host/common/MockClientContextSocket.cpp +++ b/tests/host/common/MockClientContextSocket.cpp @@ -54,7 +54,7 @@ size_t mockPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char if (usersize > CCBUFSIZE) fprintf(stderr, MOCK "CCBUFSIZE(%d) should be increased by %d bytes (-> %d)\n", CCBUFSIZE, (int)usersize - CCBUFSIZE, (int)usersize); - struct pollfd p; + struct pollfd p; size_t retsize = 0; do { @@ -75,8 +75,8 @@ size_t mockPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char } // wait for more data until timeout - p.fd = sock; - p.events = POLLIN; + p.fd = sock; + p.events = POLLIN; } while (poll(&p, 1, timeout_ms) == 1); memcpy(dst, ccinbuf, retsize); @@ -94,23 +94,28 @@ size_t mockRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf 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; - } - } - return ret; + 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 < %d) (TODO)\n", (int)ret, (int)size); + exit(EXIT_FAILURE); + } + } + return ret; } diff --git a/tests/host/common/MockTools.cpp b/tests/host/common/MockTools.cpp new file mode 100644 index 0000000000..39e4e12aa4 --- /dev/null +++ b/tests/host/common/MockTools.cpp @@ -0,0 +1,15 @@ + +#include + +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); } + +}; diff --git a/tests/host/common/MockUDPSocket.cpp b/tests/host/common/MockUDPSocket.cpp new file mode 100644 index 0000000000..8b8cefd05d --- /dev/null +++ b/tests/host/common/MockUDPSocket.cpp @@ -0,0 +1,133 @@ + +#include +#include +#include +#include +#include +#include +#include +#include + +int mockUDPSocket () +{ + int s; + if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) + { + fprintf(stderr, MOCK "UDP socket"); + exit(EXIT_FAILURE); + } + return s; +} + +bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port) +{ + struct sockaddr_in servaddr; + memset(&servaddr, 0, sizeof(servaddr)); + + // Filling server information + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl(dstaddr); + 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 to port %d failed: %s\n", port, strerror(errno)); + return false; + } + + return true; +} + + +size_t mockUDPFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize, void* addrbuf) +{ + if (addrbuf) + assert(ADDRBUFSIZE >= sizeof(sockaddr)); + socklen_t addrbufsize = ADDRBUFSIZE; ///XXX rework this addrbuf and merge tcp/udp mostly identical code + + 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 %d bytes: %s\n", (int)maxread, strerror(errno)); + ret = 0; + } + return ccinbufsize += ret; +} + +size_t mockUDPPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf, size_t& ccinbufsize, void* addrbuf) +{ + if (usersize > CCBUFSIZE) + fprintf(stderr, MOCK "CCBUFSIZE(%d) should be increased by %d bytes (-> %d)\n", CCBUFSIZE, (int)usersize - CCBUFSIZE, (int)usersize); + + struct pollfd p; + size_t retsize = 0; + do + { + if (usersize <= ccinbufsize) + { + // data already buffered + retsize = usersize; + break; + } + + // check incoming data data + mockUDPFillInBuf(sock, ccinbuf, ccinbufsize, addrbuf); + 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 mockUDPRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf, size_t& ccinbufsize, void* addrbuf) +{ + size_t copied = mockUDPPeekBytes(sock, dst, size, timeout_ms, ccinbuf, ccinbufsize, addrbuf); + // 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, const void* addrbuf) +{ + if (addrbuf) + assert(ADDRBUFSIZE >= sizeof(sockaddr)); + ///XXX rework this addrbuf and merge tcp/udp mostly identical code + + struct pollfd p; + p.fd = sock; + p.events = POLLOUT; + int ret = poll(&p, 1, timeout_ms); + if (ret == -1) + { + fprintf(stderr, MOCK "UDPContext::write: poll(%d): %s\n", sock, strerror(errno)); + return 0; + } + if (ret) + { + ret = ::sendto(sock, data, size, 0/*flags*/, (const sockaddr*)addrbuf, ADDRBUFSIZE); + 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 < %d) (TODO)\n", (int)ret, (int)size); + exit(EXIT_FAILURE); + } + } + return ret; +} diff --git a/tests/host/common/MockWiFiServer.cpp b/tests/host/common/MockWiFiServer.cpp index 467d2380c8..e09b60c7e2 100644 --- a/tests/host/common/MockWiFiServer.cpp +++ b/tests/host/common/MockWiFiServer.cpp @@ -10,6 +10,19 @@ #define int2pcb(x) ((tcp_pcb*)(long)(x)) #define pcb2int(x) ((int)(long)(x)) +WiFiServer::WiFiServer (IPAddress addr, uint16_t port) +{ +//XXX factorize + (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) diff --git a/tests/host/common/MockWiFiServerSocket.cpp b/tests/host/common/MockWiFiServerSocket.cpp index b20a6b878d..769c14238f 100644 --- a/tests/host/common/MockWiFiServerSocket.cpp +++ b/tests/host/common/MockWiFiServerSocket.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #define int2pcb(x) ((tcp_pcb*)(long)(x)) #define pcb2int(x) ((int)(long)(x)) @@ -23,6 +24,12 @@ int serverAccept (int srvsock) return clisock; } +void WiFiServer::begin (uint16_t port) +{ + _port = port; + return begin(); +} + void WiFiServer::begin () { int sock; @@ -79,3 +86,10 @@ size_t WiFiServer::write (const uint8_t *buf, size_t size) fprintf(stderr, MOCK "todo: WiFiServer::write(%p, %d)\n", buf, (int)size); return 0; } + +void WiFiServer::close () +{ + if (pcb2int(_pcb) >= 0) + ::close(pcb2int(_pcb)); + _pcb = int2pcb(-1); +} diff --git a/tests/host/common/include/ClientContext.h b/tests/host/common/include/ClientContext.h index 34dce78652..817d2b6387 100644 --- a/tests/host/common/include/ClientContext.h +++ b/tests/host/common/include/ClientContext.h @@ -20,15 +20,15 @@ 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()) + _sync(::getDefaultPrivateGlobalSyncValue()), _sock(-1) { (void)pcb; - _sock = -1; } - ClientContext (int sock) + ClientContext (int sock) : + _discard_cb(nullptr), _discard_cb_arg(nullptr), _refcnt(0), _next(nullptr), + _sync(::getDefaultPrivateGlobalSyncValue()), _sock(sock) { - _sock = sock; } err_t abort() @@ -141,25 +141,21 @@ class ClientContext return _inbufsize?: mockFillInBuf(_sock, _inbuf, _inbufsize); } - char read() + int read() { char c; - if (read(&c, 1)) - return c; - return 0; + return read(&c, 1)? c: -1; } size_t read (char* dst, size_t size) { - return mockRead(_sock, dst, size, _timeout_ms, _inbuf, _inbufsize); + return mockRead(_sock, dst, size, 0, _inbuf, _inbufsize); } int peek() { char c; - if (!mockPeekBytes(_sock, &c, 1, _timeout_ms, _inbuf, _inbufsize)) - return -1; - return c; + return peekBytes(&c, 1)? c: -1; } size_t peekBytes(char *dst, size_t size) @@ -169,6 +165,7 @@ class ClientContext void discard_received() { + fprintf(stderr, MOCK "TODO: ClientContext::discard_received()\n"); } bool wait_until_sent(int max_wait_ms = WIFICLIENT_MAX_FLUSH_WAIT_MS) diff --git a/tests/host/common/include/UdpContext.h b/tests/host/common/include/UdpContext.h new file mode 100644 index 0000000000..2d57e5396f --- /dev/null +++ b/tests/host/common/include/UdpContext.h @@ -0,0 +1,212 @@ +/* + UdpContext.h - 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 + +class UdpContext; + +#define GET_IP_HDR(pb) reinterpret_cast(((uint8_t*)((pb)->payload)) - UDP_HLEN - IP_HLEN); +#define GET_UDP_HDR(pb) reinterpret_cast(((uint8_t*)((pb)->payload)) - UDP_HLEN); + +class UdpContext +{ +public: + + typedef std::function 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) + { + return mockUDPListen(_sock, addr.addr, port); + } + + void disconnect() + { + if (_sock >= 0) + close(_sock); + _sock = -1; + } + + void setMulticastInterface(const ip_addr_t& addr) + { + fprintf(stderr, MOCK "TODO: UdpContext::setMulticastInterface\n"); + } + + 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?: mockFillInBuf(_sock, _inbuf, _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 (%d >= %d)\n", (int)pos, (int)_inbufsize); + exit(EXIT_FAILURE); + } + } + + bool isValidOffset(const size_t pos) const { + return pos <= _inbufsize; + } + + uint32_t getRemoteAddress() + { + fprintf(stderr, MOCK "TODO: implement getRemoteAddress\n"); + return 0; //ip_hdr* iphdr = GET_IP_HDR(_rx_buf); + } + + uint16_t getRemotePort() + { + fprintf(stderr, MOCK "TODO: implement UDP getRemotePort\n"); + return 0; //udp_hdr* udphdr = GET_UDP_HDR(_rx_buf); + } + + 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() + { + uint32_t a; + _inbufsize = 0; + mockUDPFillInBuf(_sock, _inbuf, _inbufsize, &a); + return _inbufsize > 0; + } + + int read() + { + char c; + return read(&c, 1)? c: -1; + } + + size_t read(char* dst, size_t size) + { + uint32_t a; + size_t ret = mockUDPRead(_sock, dst, size, _timeout_ms, _inbuf, _inbufsize, (void*)&a); + return ret; + } + + int peek() + { + char c; + uint32_t a; + return mockUDPPeekBytes(_sock, &c, 1, _timeout_ms, _inbuf, _inbufsize, &a)? c: -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 -> %d)\n", CCBUFSIZE, (int)(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 a = lwip_htonl(addr? addr->addr: 0); + size_t ret = mockUDPWrite(_sock, (const uint8_t*)_outbuf, _outbufsize, _timeout_ms, &a); + _outbufsize = 0; + return ret > 0; + } + +private: + 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; +}; + +#endif//UDPCONTEXT_H diff --git a/tests/host/common/mock.h b/tests/host/common/mock.h index f9b92523ab..9372a05bb4 100644 --- a/tests/host/common/mock.h +++ b/tests/host/common/mock.h @@ -16,23 +16,42 @@ typedef uint32_t uint32; #include -#define lwip_htons htons -#define lwip_htonl htonl +// + +// htontoh code in common/MockTools.cpp +#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS + +// #include #define RANDOM_REG32 ((uint32_t)random()) // +#undef INADDR_NONE + +// + #ifdef __cplusplus #ifndef CCBUFSIZE #define CCBUFSIZE 512 #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); -#endif - int serverAccept (int sock); + +// udp +#define ADDRBUFSIZE 32 // ipv6:16 ipv4:4 +int mockUDPSocket (); +bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port); +size_t mockUDPFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize, void* addrbuf); +size_t mockUDPPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf, size_t& ccinbufsize, void* addrbuf); +size_t mockUDPRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf, size_t& ccinbufsize, void* addrbuf); +size_t mockUDPWrite (int sock, const uint8_t* data, size_t size, int timeout_ms, const void* addrbuf); + +#endif // __cplusplus diff --git a/tests/host/common/user_interface.cpp b/tests/host/common/user_interface.cpp index 814e873219..1e3ca9b6ba 100644 --- a/tests/host/common/user_interface.cpp +++ b/tests/host/common/user_interface.cpp @@ -1,5 +1,5 @@ -#include +#include extern "C" { @@ -79,9 +79,9 @@ bool wifi_get_ip_info (uint8 if_index, struct ip_info *info) fprintf(stderr, "we are not AP"); //XXXTODO (give ip address of default route's interface?) - info->ip.addr = htonl(0x7f000001); - info->netmask.addr = htonl(0xff000000); - info->gw.addr = htonl(0x7f000001); + info->ip.addr = lwip_htonl(0x7f000001); + info->netmask.addr = lwip_htonl(0xff000000); + info->gw.addr = lwip_htonl(0x7f000001); return true; } From 0520303aa97db30acfee558eadf2ed66db9dac56 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Mon, 12 Nov 2018 18:51:24 +0100 Subject: [PATCH 13/50] minor changes to the core --- libraries/ESP8266WiFi/src/include/UdpContext.h | 3 ++- libraries/ESP8266mDNS/ESP8266mDNS.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/ESP8266WiFi/src/include/UdpContext.h b/libraries/ESP8266WiFi/src/include/UdpContext.h index 2a6310a76e..6503affad0 100644 --- a/libraries/ESP8266WiFi/src/include/UdpContext.h +++ b/libraries/ESP8266WiFi/src/include/UdpContext.h @@ -174,7 +174,7 @@ class UdpContext 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 @@ class UdpContext void flush() { + //XXX this does not follow Arduino's flush definition if (!_rx_buf) return; diff --git a/libraries/ESP8266mDNS/ESP8266mDNS.cpp b/libraries/ESP8266mDNS/ESP8266mDNS.cpp index c754a2b8cf..9662b8bb8e 100644 --- a/libraries/ESP8266mDNS/ESP8266mDNS.cpp +++ b/libraries/ESP8266mDNS/ESP8266mDNS.cpp @@ -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){ From 3897ebeb4e4913f77b89ff70872f79d3493ef733 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Wed, 14 Nov 2018 00:54:09 +0100 Subject: [PATCH 14/50] WIP basic udp working --- libraries/ESP8266WiFi/src/WiFiUdp.cpp | 6 +- tests/host/Makefile | 3 +- tests/host/common/MockUDPSocket.cpp | 110 ++++++++++++++++--------- tests/host/common/MockWiFiServer.cpp | 6 ++ tests/host/common/include/UdpContext.h | 57 +++++++++---- tests/host/common/mock.h | 13 ++- 6 files changed, 127 insertions(+), 68 deletions(-) diff --git a/libraries/ESP8266WiFi/src/WiFiUdp.cpp b/libraries/ESP8266WiFi/src/WiFiUdp.cpp index 5e42473089..3b936d7c87 100644 --- a/libraries/ESP8266WiFi/src/WiFiUdp.cpp +++ b/libraries/ESP8266WiFi/src/WiFiUdp.cpp @@ -38,7 +38,7 @@ extern "C" #include "lwip/inet.h" #include "lwip/igmp.h" #include "lwip/mem.h" -#include "include/UdpContext.h" +#include 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; } diff --git a/tests/host/Makefile b/tests/host/Makefile index 4cebf82e2d..7aa78c27b1 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -82,7 +82,7 @@ PREINCLUDES := \ CXXFLAGS += -std=c++11 -Wall -Werror -coverage -O0 -fno-common -g CFLAGS += -std=c99 -Wall -Werror -coverage -O0 -fno-common -g -LDFLAGS += -coverage -O0 +LDFLAGS += -coverage -O0 -g VALGRINDFLAGS += --leak-check=full --track-origins=yes --error-limit=no --show-leak-kinds=all --error-exitcode=999 # CXXFLAGS += -Wno-nonnull-compare # libraries/ESP8266WiFi/src/include/UdpContext.h:85:9: error: nonnull argument ‘this’ compared to NULL [-Werror=nonnull-compare] -- (if(this != 0)) @@ -165,6 +165,7 @@ MOCK_ARDUINO_LIBS := \ ESP8266WiFiSTA.cpp \ ESP8266WiFiScan.cpp \ WiFiClient.cpp \ + WiFiUdp.cpp \ ) \ $(addprefix ESP8266WebServer/src/,\ ESP8266WebServer.cpp \ diff --git a/tests/host/common/MockUDPSocket.cpp b/tests/host/common/MockUDPSocket.cpp index 8b8cefd05d..1e5e29b703 100644 --- a/tests/host/common/MockUDPSocket.cpp +++ b/tests/host/common/MockUDPSocket.cpp @@ -11,15 +11,15 @@ int mockUDPSocket () { int s; - if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) + if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1 || fcntl(s, F_SETFL, O_NONBLOCK) == -1) { - fprintf(stderr, MOCK "UDP socket"); + fprintf(stderr, MOCK "UDP socket: %s", strerror(errno)); exit(EXIT_FAILURE); } return s; } -bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port) +bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast) { struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); @@ -35,77 +35,100 @@ bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port) fprintf(stderr, MOCK "UDP bind to port %d failed: %s\n", port, strerror(errno)); return false; } + else + fprintf(stderr, MOCK "UDP server on port %d (sock=%d)\n", (int)port, (int)sock); + + if (mcast) + { + // https://web.cs.wpi.edu/~claypool/courses/4514-B99/samples/multicast.c + struct ip_mreq mreq; + mreq.imr_multiaddr.s_addr = htonl(mcast); + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + 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, void* addrbuf) +size_t mockUDPFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize, void* addrbuf, uint32_t* addrbufsize) { - if (addrbuf) - assert(ADDRBUFSIZE >= sizeof(sockaddr)); - socklen_t addrbufsize = ADDRBUFSIZE; ///XXX rework this addrbuf and merge tcp/udp mostly identical code + socklen_t realaddrbufsize = addrbufsize? *addrbufsize: 0; size_t maxread = CCBUFSIZE - ccinbufsize; - ssize_t ret = ::recvfrom(sock, ccinbuf + ccinbufsize, maxread, 0/*flags*/, (sockaddr*)addrbuf, &addrbufsize); + ssize_t ret = ::recvfrom(sock, ccinbuf + ccinbufsize, maxread, 0/*flags*/, (sockaddr*)addrbuf, &realaddrbufsize); + *addrbufsize = realaddrbufsize; if (ret == -1) { if (errno != EAGAIN) fprintf(stderr, MOCK "UDPContext::(read/peek): filling buffer for %d bytes: %s\n", (int)maxread, strerror(errno)); ret = 0; } + return ccinbufsize += ret; } -size_t mockUDPPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf, size_t& ccinbufsize, void* addrbuf) +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 %d bytes: %s\n", (int)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 %d bytes (-> %d)\n", CCBUFSIZE, (int)usersize - CCBUFSIZE, (int)usersize); - struct pollfd p; size_t retsize = 0; - do + if (ccinbufsize) { - if (usersize <= ccinbufsize) - { - // data already buffered - retsize = usersize; - break; - } - - // check incoming data data - mockUDPFillInBuf(sock, ccinbuf, ccinbufsize, addrbuf); - 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); - + // 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, void* addrbuf) +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, addrbuf); - // swallow (XXX use a circular buffer) + 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, const void* addrbuf) +size_t mockUDPWrite (int sock, const uint8_t* data, size_t size, int timeout_ms, uint32_t ipv4, uint16_t port) { - if (addrbuf) - assert(ADDRBUFSIZE >= sizeof(sockaddr)); - ///XXX rework this addrbuf and merge tcp/udp mostly identical code - struct pollfd p; p.fd = sock; p.events = POLLOUT; @@ -117,7 +140,12 @@ size_t mockUDPWrite (int sock, const uint8_t* data, size_t size, int timeout_ms, } if (ret) { - ret = ::sendto(sock, data, size, 0/*flags*/, (const sockaddr*)addrbuf, ADDRBUFSIZE); + // 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); + 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)); diff --git a/tests/host/common/MockWiFiServer.cpp b/tests/host/common/MockWiFiServer.cpp index e09b60c7e2..b65b4e9e54 100644 --- a/tests/host/common/MockWiFiServer.cpp +++ b/tests/host/common/MockWiFiServer.cpp @@ -41,3 +41,9 @@ WiFiClient WiFiServer::available (uint8_t* status) return WiFiClient(new ClientContext(serverAccept(pcb2int(_pcb)))); return WiFiClient(); } + +// static declaration + +#include +uint32_t UdpContext::staticMCastAddr = 0; + diff --git a/tests/host/common/include/UdpContext.h b/tests/host/common/include/UdpContext.h index 2d57e5396f..f7fb7b7dd5 100644 --- a/tests/host/common/include/UdpContext.h +++ b/tests/host/common/include/UdpContext.h @@ -53,7 +53,7 @@ class UdpContext } } - bool connect(ip_addr_t addr, uint16_t port) + bool connect (ip_addr_t addr, uint16_t port) { _dst = addr; _dstport = port; @@ -62,7 +62,7 @@ class UdpContext bool listen(ip_addr_t addr, uint16_t port) { - return mockUDPListen(_sock, addr.addr, port); + return mockUDPListen(_sock, addr.addr, port, staticMCastAddr); } void disconnect() @@ -90,7 +90,7 @@ class UdpContext size_t getSize() { - return _inbufsize?: mockFillInBuf(_sock, _inbuf, _inbufsize); + return _inbufsize; } size_t tell() const @@ -114,14 +114,12 @@ class UdpContext uint32_t getRemoteAddress() { - fprintf(stderr, MOCK "TODO: implement getRemoteAddress\n"); - return 0; //ip_hdr* iphdr = GET_IP_HDR(_rx_buf); + return _dst.addr; } uint16_t getRemotePort() { - fprintf(stderr, MOCK "TODO: implement UDP getRemotePort\n"); - return 0; //udp_hdr* udphdr = GET_UDP_HDR(_rx_buf); + return _dstport; } uint32_t getDestAddress() @@ -138,10 +136,14 @@ class UdpContext bool next() { - uint32_t a; _inbufsize = 0; - mockUDPFillInBuf(_sock, _inbuf, _inbufsize, &a); - return _inbufsize > 0; + mockUDPFillInBuf(_sock, _inbuf, _inbufsize, addrsize, addr, _dstport); + if (_inbufsize > 0) + { + translate_addr(); + return true; + } + return false; } int read() @@ -152,16 +154,13 @@ class UdpContext size_t read(char* dst, size_t size) { - uint32_t a; - size_t ret = mockUDPRead(_sock, dst, size, _timeout_ms, _inbuf, _inbufsize, (void*)&a); - return ret; + return mockUDPRead(_sock, dst, size, _timeout_ms, _inbuf, _inbufsize); } int peek() { char c; - uint32_t a; - return mockUDPPeekBytes(_sock, &c, 1, _timeout_ms, _inbuf, _inbufsize, &a)? c: -1; + return mockUDPPeekBytes(_sock, &c, 1, _timeout_ms, _inbuf, _inbufsize)?: -1; } void flush() @@ -187,13 +186,27 @@ class UdpContext bool send (ip_addr_t* addr = 0, uint16_t port = 0) { - uint32_t a = lwip_htonl(addr? addr->addr: 0); - size_t ret = mockUDPWrite(_sock, (const uint8_t*)_outbuf, _outbufsize, _timeout_ms, &a); + 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; } +public: + + static uint32_t staticMCastAddr; + private: + + void translate_addr () + { + if (addrsize == 4) + ip4_addr_set_u32(&ip_2_ip4(_dst), *(uint32_t*)addr); // XXX should use lwip_ntohl? + else + fprintf(stderr, MOCK "TODO unhandled udp address of size %d\n", (int)addrsize); + } + int _sock = -1; rxhandler_t _on_rx; int _refcnt = 0; @@ -207,6 +220,16 @@ class UdpContext 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 diff --git a/tests/host/common/mock.h b/tests/host/common/mock.h index 9372a05bb4..74c800c302 100644 --- a/tests/host/common/mock.h +++ b/tests/host/common/mock.h @@ -34,7 +34,7 @@ typedef uint32_t uint32; #ifdef __cplusplus #ifndef CCBUFSIZE -#define CCBUFSIZE 512 +#define CCBUFSIZE 8192 #endif // tcp @@ -48,10 +48,9 @@ int serverAccept (int sock); // udp #define ADDRBUFSIZE 32 // ipv6:16 ipv4:4 int mockUDPSocket (); -bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port); -size_t mockUDPFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize, void* addrbuf); -size_t mockUDPPeekBytes (int sock, char* dst, size_t usersize, int timeout_ms, char* ccinbuf, size_t& ccinbufsize, void* addrbuf); -size_t mockUDPRead (int sock, char* dst, size_t size, int timeout_ms, char* ccinbuf, size_t& ccinbufsize, void* addrbuf); -size_t mockUDPWrite (int sock, const uint8_t* data, size_t size, int timeout_ms, const void* addrbuf); - +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); #endif // __cplusplus From c29a35d12aafdfe5201390620bea2875b4cb15e3 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Wed, 14 Nov 2018 03:05:18 +0100 Subject: [PATCH 15/50] WIP mdns --- cores/esp8266/spiffs_api.h | 4 +-- libraries/ESP8266WiFi/src/WiFiUdp.cpp | 4 +-- tests/host/Makefile | 7 +++-- tests/host/common/ArduinoMain.cpp | 36 ++++++++++++++++++++++++++ tests/host/common/MockTools.cpp | 10 +++++++ tests/host/common/MockUDPSocket.cpp | 6 ++--- tests/host/common/MockWiFiServer.cpp | 2 ++ tests/host/common/include/UdpContext.h | 19 +++++++++++--- tests/host/common/mock.h | 16 ++++++++++++ tests/host/common/user_interface.cpp | 7 ++++- 10 files changed, 97 insertions(+), 14 deletions(-) diff --git a/cores/esp8266/spiffs_api.h b/cores/esp8266/spiffs_api.h index 4ce8d3e6ba..ef47f79be4 100644 --- a/cores/esp8266/spiffs_api.h +++ b/cores/esp8266/spiffs_api.h @@ -221,8 +221,8 @@ class SPIFFSImpl : public FSImpl if (!_workBuf) { DEBUGV("SPIFFSImpl: allocating %d+%d+%d=%d bytes\r\n", - workBufSize, fdsBufSize, cacheBufSize, - workBufSize + fdsBufSize + cacheBufSize); + (int)workBufSize, (int)fdsBufSize, (int)cacheBufSize, + (int)(workBufSize + fdsBufSize + cacheBufSize)); _workBuf.reset(new uint8_t[workBufSize]); _fdsBuf.reset(new uint8_t[fdsBufSize]); _cacheBuf.reset(new uint8_t[cacheBufSize]); diff --git a/libraries/ESP8266WiFi/src/WiFiUdp.cpp b/libraries/ESP8266WiFi/src/WiFiUdp.cpp index 3b936d7c87..9be50c1342 100644 --- a/libraries/ESP8266WiFi/src/WiFiUdp.cpp +++ b/libraries/ESP8266WiFi/src/WiFiUdp.cpp @@ -286,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(); } } @@ -294,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(); } } diff --git a/tests/host/Makefile b/tests/host/Makefile index 7aa78c27b1..e0e2fb19ea 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -80,7 +80,10 @@ PREINCLUDES := \ -include common/mock.h \ -include common/c_types.h \ -CXXFLAGS += -std=c++11 -Wall -Werror -coverage -O0 -fno-common -g +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 + +CXXFLAGS += $(DEBUG) -std=c++11 -Wall -Werror -coverage -O0 -fno-common -g CFLAGS += -std=c99 -Wall -Werror -coverage -O0 -fno-common -g LDFLAGS += -coverage -O0 -g VALGRINDFLAGS += --leak-check=full --track-origins=yes --error-limit=no --show-leak-kinds=all --error-exitcode=999 @@ -172,9 +175,9 @@ MOCK_ARDUINO_LIBS := \ Parsing.cpp \ detail/mimetable.cpp \ ) \ + ESP8266mDNS/ESP8266mDNS.cpp \ ) -# ESP8266mDNS/ESP8266mDNS.cpp \ MOCK_ARDUINO_LIBS += \ diff --git a/tests/host/common/ArduinoMain.cpp b/tests/host/common/ArduinoMain.cpp index 3a3dcb4e8b..2def2fd349 100644 --- a/tests/host/common/ArduinoMain.cpp +++ b/tests/host/common/ArduinoMain.cpp @@ -1,7 +1,28 @@ #include +#include +#include "lwip/opt.h" +#include "lwip/udp.h" +#include "lwip/inet.h" +#include "lwip/igmp.h" +#include "lwip/mem.h" +#include +#include + #include // usleep +#include + +std::map udps; + +void register_udp (int sock, UdpContext* udp) +{ + if (udp) + udps[sock] = udp; + else + udps.erase(sock); +} + int main (void) { @@ -9,7 +30,22 @@ int main (void) while (true) { 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\n", (int)p.fd); + udp.second->mock_cb(); + } + } + } return 0; } diff --git a/tests/host/common/MockTools.cpp b/tests/host/common/MockTools.cpp index 39e4e12aa4..123552cf58 100644 --- a/tests/host/common/MockTools.cpp +++ b/tests/host/common/MockTools.cpp @@ -1,5 +1,6 @@ #include +#include extern "C" { @@ -12,4 +13,13 @@ 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; +} + }; diff --git a/tests/host/common/MockUDPSocket.cpp b/tests/host/common/MockUDPSocket.cpp index 1e5e29b703..cd64f62e90 100644 --- a/tests/host/common/MockUDPSocket.cpp +++ b/tests/host/common/MockUDPSocket.cpp @@ -26,7 +26,7 @@ bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast) // Filling server information servaddr.sin_family = AF_INET; - servaddr.sin_addr.s_addr = htonl(dstaddr); + servaddr.sin_addr.s_addr = dstaddr; servaddr.sin_port = htons(port); // Bind the socket with the server address @@ -42,8 +42,8 @@ bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast) { // https://web.cs.wpi.edu/~claypool/courses/4514-B99/samples/multicast.c struct ip_mreq mreq; - mreq.imr_multiaddr.s_addr = htonl(mcast); - mreq.imr_interface.s_addr = htonl(INADDR_ANY); + mreq.imr_multiaddr.s_addr = mcast; + mreq.imr_interface.s_addr = 0;//htonl(INADDR_ANY); 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); diff --git a/tests/host/common/MockWiFiServer.cpp b/tests/host/common/MockWiFiServer.cpp index b65b4e9e54..31c13e1db3 100644 --- a/tests/host/common/MockWiFiServer.cpp +++ b/tests/host/common/MockWiFiServer.cpp @@ -7,6 +7,8 @@ #include +extern "C" const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY); + #define int2pcb(x) ((tcp_pcb*)(long)(x)) #define pcb2int(x) ((int)(long)(x)) diff --git a/tests/host/common/include/UdpContext.h b/tests/host/common/include/UdpContext.h index f7fb7b7dd5..ff1cc074f2 100644 --- a/tests/host/common/include/UdpContext.h +++ b/tests/host/common/include/UdpContext.h @@ -62,19 +62,25 @@ class UdpContext bool listen(ip_addr_t addr, uint16_t port) { - return mockUDPListen(_sock, addr.addr, port, staticMCastAddr); + 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) { - fprintf(stderr, MOCK "TODO: UdpContext::setMulticastInterface\n"); + // not needed on posix, multicast is associated with + // socket and its address (0.0.0.0) = all interfaces } void setMulticastTTL(int ttl) @@ -165,8 +171,8 @@ class UdpContext void flush() { - fprintf(stderr, MOCK "UdpContext::flush() does not follow arduino's flush concept\n"); - exit(EXIT_FAILURE); + //fprintf(stderr, MOCK "UdpContext::flush() does not follow arduino's flush concept\n"); + //exit(EXIT_FAILURE); // would be: _inbufsize = 0; } @@ -192,6 +198,11 @@ class UdpContext _outbufsize = 0; return ret > 0; } + + void mock_cb (void) + { + if (_on_rx) _on_rx(); + } public: diff --git a/tests/host/common/mock.h b/tests/host/common/mock.h index 74c800c302..0038357156 100644 --- a/tests/host/common/mock.h +++ b/tests/host/common/mock.h @@ -33,6 +33,18 @@ typedef uint32_t uint32; // #ifdef __cplusplus +extern "C" { +#endif +int ets_printf (const char* fmt, ...) __attribute__ ((format (printf, 1, 2))); +#define os_printf_plus ets_printf +#ifdef __cplusplus +} +#endif + +// + +#ifdef __cplusplus + #ifndef CCBUFSIZE #define CCBUFSIZE 8192 #endif @@ -53,4 +65,8 @@ size_t mockUDPFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize, uint8_t& 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); + #endif // __cplusplus diff --git a/tests/host/common/user_interface.cpp b/tests/host/common/user_interface.cpp index 1e3ca9b6ba..7004c0770a 100644 --- a/tests/host/common/user_interface.cpp +++ b/tests/host/common/user_interface.cpp @@ -79,10 +79,15 @@ bool wifi_get_ip_info (uint8 if_index, struct ip_info *info) fprintf(stderr, "we are not AP"); //XXXTODO (give ip address of default route's interface?) +#if 1 + info->ip.addr = lwip_htonl(0xc0a80108); + info->netmask.addr = lwip_htonl(0xffffff00); + info->gw.addr = lwip_htonl(0xc0a801fe); +#else info->ip.addr = lwip_htonl(0x7f000001); info->netmask.addr = lwip_htonl(0xff000000); info->gw.addr = lwip_htonl(0x7f000001); - +#endif return true; } From c2f8b456452e88c09f534a2864f7cba27dea0bbe Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Wed, 14 Nov 2018 15:52:04 +0100 Subject: [PATCH 16/50] WIP --- cores/esp8266/Esp.cpp | 5 +- cores/esp8266/Updater.cpp | 16 +- libraries/DNSServer/src/DNSServer.cpp | 6 +- .../src/ESP8266HTTPClient.cpp | 2 +- tests/host/Makefile | 50 +++++-- tests/host/common/Arduino.cpp | 16 ++ tests/host/common/ArduinoMain.cpp | 38 ++++- tests/host/common/ArduinoWire.cpp | 15 ++ tests/host/common/EEPROM.h | 51 +++++++ tests/host/common/MockEEPROM.cpp | 74 +++++++++ tests/host/common/MockEsp.cpp | 138 +++++++++++++++++ tests/host/common/MockSPI.cpp | 33 +++++ tests/host/common/esp8266_peri.h | 7 + tests/host/common/include/UdpContext.h | 2 + tests/host/common/interrupts.h | 0 tests/host/common/mock.h | 15 +- tests/host/common/user_interface.cpp | 140 ++++++++++++++++-- 17 files changed, 569 insertions(+), 39 deletions(-) create mode 100644 tests/host/common/EEPROM.h create mode 100644 tests/host/common/MockEEPROM.cpp create mode 100644 tests/host/common/MockEsp.cpp create mode 100644 tests/host/common/MockSPI.cpp create mode 100644 tests/host/common/esp8266_peri.h create mode 100644 tests/host/common/interrupts.h diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index 42715605c1..97a7955cd2 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -22,7 +22,7 @@ #include "flash_utils.h" #include "eboot_command.h" #include -#include "interrupts.h" +#include #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(); } @@ -480,7 +481,7 @@ uint32_t EspClass::getFreeSketchSpace() { uint32_t usedSize = getSketchSize(); // round one sector up uint32_t freeSpaceStart = (usedSize + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1)); - uint32_t freeSpaceEnd = (uint32_t)&_SPIFFS_start - 0x40200000; + uint32_t freeSpaceEnd = (uint32_t)(unsigned long)&_SPIFFS_start - 0x40200000; #ifdef DEBUG_SERIAL DEBUG_SERIAL.printf("usedSize=%u freeSpaceStart=%u freeSpaceEnd=%u\r\n", usedSize, freeSpaceStart, freeSpaceEnd); diff --git a/cores/esp8266/Updater.cpp b/cores/esp8266/Updater.cpp index c82f368c6b..8c0dce66a0 100644 --- a/cores/esp8266/Updater.cpp +++ b/cores/esp8266/Updater.cpp @@ -1,8 +1,8 @@ #include "Updater.h" #include "Arduino.h" #include "eboot_command.h" -#include "interrupts.h" -#include "esp8266_peri.h" +#include +#include //#define DEBUG_UPDATER Serial @@ -89,7 +89,7 @@ bool UpdaterClass::begin(size_t size, int command, int ledPin, uint8_t ledOn) { //size of current sketch rounded to a sector uint32_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; + uint32_t updateEndAddress = (uint32_t)(unsigned long)&_SPIFFS_start - 0x40200000; //size of the update rounded to a sector uint32_t roundedSize = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1)); //address where we will start writing the update @@ -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 = (uint32_t)(unsigned long)&_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%08X (%d)\n", (unsigned)_size, (unsigned)_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:%u/%u\n", getError(), (unsigned)progress(), (unsigned)_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%08X\n", _startAddress, (unsigned)_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%08X\n", _startAddress, (unsigned)_size); #endif } diff --git a/libraries/DNSServer/src/DNSServer.cpp b/libraries/DNSServer/src/DNSServer.cpp index e75af30cd7..5e1382bcd1 100644 --- a/libraries/DNSServer/src/DNSServer.cpp +++ b/libraries/DNSServer/src/DNSServer.cpp @@ -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; diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index ecac309384..d3369ddc69 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -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 %d mismatch!.\n", bytesWritten, (int)size); DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] ERROR SEND PAYLOAD FAILED!"); return returnError(HTTPC_ERROR_SEND_PAYLOAD_FAILED); } else { diff --git a/tests/host/Makefile b/tests/host/Makefile index e0e2fb19ea..abc9b50904 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -80,8 +80,10 @@ PREINCLUDES := \ -include common/mock.h \ -include common/c_types.h \ +ifneq ($(D),) 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 -O0 -fno-common -g CFLAGS += -std=c99 -Wall -Werror -coverage -O0 -fno-common -g @@ -89,6 +91,7 @@ LDFLAGS += -coverage -O0 -g VALGRINDFLAGS += --leak-check=full --track-origins=yes --error-limit=no --show-leak-kinds=all --error-exitcode=999 # CXXFLAGS += -Wno-nonnull-compare # libraries/ESP8266WiFi/src/include/UdpContext.h:85:9: error: nonnull argument ‘this’ compared to NULL [-Werror=nonnull-compare] -- (if(this != 0)) +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)) remduplicates = $(strip $(if $1,$(firstword $1) $(call remduplicates,$(filter-out $(firstword $1),$1)))) @@ -157,7 +160,11 @@ $(OUTPUT_BINARY): $(CPP_OBJECTS_TESTS) $(BINDIR)/core.a ################################################# # building ino sources -MOCK_ARDUINO_LIBS := \ +ARDUINO_LIBS := \ + $(addprefix $(CORE_PATH)/,\ + IPAddress.cpp \ + Updater.cpp \ + ) \ $(addprefix ../../libraries/,\ $(addprefix ESP8266WiFi/src/,\ ESP8266WiFi.cpp \ @@ -176,11 +183,15 @@ MOCK_ARDUINO_LIBS := \ detail/mimetable.cpp \ ) \ ESP8266mDNS/ESP8266mDNS.cpp \ - ) + ArduinoOTA/ArduinoOTA.cpp \ + DNSServer/src/DNSServer.cpp \ + ESP8266AVRISP/src/ESP8266AVRISP.cpp \ + ESP8266HTTPClient/src/ESP8266HTTPClient.cpp \ + ) \ -MOCK_ARDUINO_LIBS += \ +MOCK_ARDUINO_LIBS := \ common/MockClientContextSocket.cpp \ common/MockClientContext.cpp \ common/MockWiFiServerSocket.cpp \ @@ -188,11 +199,11 @@ MOCK_ARDUINO_LIBS += \ common/MockUDPSocket.cpp \ common/ArduinoWire.cpp \ common/MockTools.cpp \ + common/MockEsp.cpp \ + common/MockEEPROM.cpp \ + common/MockSPI.cpp \ -ARDUINO_LIBS += $(addprefix $(CORE_PATH)/,\ - IPAddress.cpp \ -) - +ARDUINO_LIBS += CPP_SOURCES_CORE_EMU = \ $(MOCK_CPP_FILES_EMU) \ $(CORE_CPP_FILES) \ @@ -206,18 +217,37 @@ bin/fullcore.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE_EMU) ranlib -c $@ .PRECIOUS: %.cpp.o -%: %.cpp.o bin/fullcore.a +%: %.ino.cpp.o bin/fullcore.a $(CXX) $(LDFLAGS) $< bin/fullcore.a -o $@ ln -sf ../$@ $(BINDIR) .PRECIOUS: %.cpp -%.cpp: %.ino - cp $< $@ +%.ino.cpp: %.ino + @s=$<; \ + n=$${s##*/}; \ + (cd $${s%/*}; \ + echo "#include \"$$n\""; \ + for i in *.ino; do \ + test "$$i" = "$$n" || echo "#include \"$$i\""; \ + done; \ + ) > $@ ################################################# # Makefile.inc.ino generation -include $(BINDIR)/Makefile.inc.ino +.PHONY: list +list: + # copy examples locally + @for dir in ../../libraries/*/examples; do \ + exampledir=$${dir%/*}; \ + exampledirname=$${exampledir##*/}; \ + for subdir in $$dir/*; do \ + exname=$${subdir##*/}; \ + echo "$$subdir/$$exname"; \ + done; \ + done; \ + $(BINDIR)/Makefile.inc.ino: # copy examples locally all=""; \ diff --git a/tests/host/common/Arduino.cpp b/tests/host/common/Arduino.cpp index 9c8fa59680..b758ec7201 100644 --- a/tests/host/common/Arduino.cpp +++ b/tests/host/common/Arduino.cpp @@ -25,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(); @@ -39,3 +50,8 @@ extern "C" void delay(unsigned long ms) { usleep(ms * 1000); } + +extern "C" void delayMicroseconds(unsigned int us) +{ + usleep(us); +} diff --git a/tests/host/common/ArduinoMain.cpp b/tests/host/common/ArduinoMain.cpp index 2def2fd349..6956a59497 100644 --- a/tests/host/common/ArduinoMain.cpp +++ b/tests/host/common/ArduinoMain.cpp @@ -11,6 +11,8 @@ #include #include // usleep +#include + #include std::map udps; @@ -23,9 +25,43 @@ void register_udp (int sock, UdpContext* udp) 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 \n" + ,argv0); + exit(exitcode); +} + +static struct option options[] = +{ + { "help", no_argument, NULL, 'h' }, + { "interface", required_argument, NULL, 'i' }, +}; -int main (void) +int main (int argc, char* const argv []) { + for (;;) + { + int n = getopt_long(argc, argv, "hi:", options, NULL); + if (n < 0) + break; + switch (n) + { + case 'h': + help(argv[0], EXIT_SUCCESS); + break; + case 'i': + host_interface = optarg; + break; + } + } + setup(); while (true) { diff --git a/tests/host/common/ArduinoWire.cpp b/tests/host/common/ArduinoWire.cpp index be2e229f3b..24efbf31c0 100644 --- a/tests/host/common/ArduinoWire.cpp +++ b/tests/host/common/ArduinoWire.cpp @@ -24,3 +24,18 @@ 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); +} diff --git a/tests/host/common/EEPROM.h b/tests/host/common/EEPROM.h new file mode 100644 index 0000000000..0a72f75ee9 --- /dev/null +++ b/tests/host/common/EEPROM.h @@ -0,0 +1,51 @@ + +#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 + 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 + 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 diff --git a/tests/host/common/MockEEPROM.cpp b/tests/host/common/MockEEPROM.cpp new file mode 100644 index 0000000000..cfc01ff995 --- /dev/null +++ b/tests/host/common/MockEEPROM.cpp @@ -0,0 +1,74 @@ + +#ifndef __EEPROM_H +#define __EEPROM_H + +#include + +#include +#include +#include +#include +#include + +#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 0 +void EEPROMClass::update (int x, char c) +{ + put(x, c); +} +#endif + +#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_EEPROM) +EEPROMClass EEPROM; +#endif + +#endif diff --git a/tests/host/common/MockEsp.cpp b/tests/host/common/MockEsp.cpp new file mode 100644 index 0000000000..e24a8d408f --- /dev/null +++ b/tests/host/common/MockEsp.cpp @@ -0,0 +1,138 @@ + +#include +#include + +#include + +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); +} \ No newline at end of file diff --git a/tests/host/common/MockSPI.cpp b/tests/host/common/MockSPI.cpp new file mode 100644 index 0000000000..1409612f41 --- /dev/null +++ b/tests/host/common/MockSPI.cpp @@ -0,0 +1,33 @@ + +#include + +#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; +} diff --git a/tests/host/common/esp8266_peri.h b/tests/host/common/esp8266_peri.h new file mode 100644 index 0000000000..b7b17675b8 --- /dev/null +++ b/tests/host/common/esp8266_peri.h @@ -0,0 +1,7 @@ + +#ifndef FAKE_ESP8266_PERI_H +#define FAKE_ESP8266_PERI_H + +const int GPI = 0; + +#endif \ No newline at end of file diff --git a/tests/host/common/include/UdpContext.h b/tests/host/common/include/UdpContext.h index ff1cc074f2..f803e95f08 100644 --- a/tests/host/common/include/UdpContext.h +++ b/tests/host/common/include/UdpContext.h @@ -21,6 +21,8 @@ #ifndef UDPCONTEXT_H #define UDPCONTEXT_H +#include + class UdpContext; #define GET_IP_HDR(pb) reinterpret_cast(((uint8_t*)((pb)->payload)) - UDP_HLEN - IP_HLEN); diff --git a/tests/host/common/interrupts.h b/tests/host/common/interrupts.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/host/common/mock.h b/tests/host/common/mock.h index 0038357156..f9c455cdb6 100644 --- a/tests/host/common/mock.h +++ b/tests/host/common/mock.h @@ -37,6 +37,9 @@ extern "C" { #endif int ets_printf (const char* fmt, ...) __attribute__ ((format (printf, 1, 2))); #define os_printf_plus ets_printf + +extern const char* host_interface; // cmdline parameter + #ifdef __cplusplus } #endif @@ -67,6 +70,16 @@ size_t mockUDPRead (int sock, char* dst, size_t size, int timeout_ms, char* ccin 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); +void register_udp (int sock, UdpContext* udp = nullptr); + +class InterruptLock { }; + +// + +#define ESP8266 +#define A0 0 +#define LED_BUILTIN 0 + +// #endif // __cplusplus diff --git a/tests/host/common/user_interface.cpp b/tests/host/common/user_interface.cpp index 7004c0770a..b15cbf7fb7 100644 --- a/tests/host/common/user_interface.cpp +++ b/tests/host/common/user_interface.cpp @@ -1,6 +1,15 @@ #include +#include +#include +#include +#include +#include +#include +#include + + extern "C" { @@ -74,20 +83,49 @@ void wifi_fpm_set_sleep_type (sleep_type_t type) bool wifi_get_ip_info (uint8 if_index, struct ip_info *info) { - //XXXTODO - if (if_index != STATION_IF) - fprintf(stderr, "we are not AP"); + 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); + + //if (if_index != STATION_IF) + // fprintf(stderr, "we are not AP"); - //XXXTODO (give ip address of default route's interface?) -#if 1 - info->ip.addr = lwip_htonl(0xc0a80108); - info->netmask.addr = lwip_htonl(0xffffff00); - info->gw.addr = lwip_htonl(0xc0a801fe); -#else - info->ip.addr = lwip_htonl(0x7f000001); - info->netmask.addr = lwip_htonl(0xff000000); - info->gw.addr = lwip_htonl(0x7f000001); -#endif + info->ip.addr = ipv4; + info->netmask.addr = mask; + info->gw.addr = ipv4; + return true; } @@ -250,6 +288,82 @@ 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; +} + + /////////////////////////////////////// // not user_interface From 005cd4296bea6664a2f481b7b82a1b29c86ae2ea Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Wed, 14 Nov 2018 16:10:58 +0100 Subject: [PATCH 17/50] WIP --- tests/host/README | 27 +++++++++++++++++++++++++++ tests/host/common/MockUDPSocket.cpp | 7 +++++++ 2 files changed, 34 insertions(+) create mode 100644 tests/host/README diff --git a/tests/host/README b/tests/host/README new file mode 100644 index 0000000000..06bc00e4e6 --- /dev/null +++ b/tests/host/README @@ -0,0 +1,27 @@ + +Host emulation (WIP) +-------------------- + +Regular host test: + make + +Build all examples with debug enabled: (WIP) + make D=1 examples + +Show the example list: + make list + +Build one example + make D=1 ../../libraries/esp8266/examples/Blink/Blink +run it: + ./bin/Blink -h + + +Interesting examples: + make D=1 ../../libraries/esp8266/examples/Blink/Blink + make D=1 ../../libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient + make D=1 ../../libraries/ESP8266WebServer/examples/HelloServer/HelloServer + +Needs tweaking: + make D=1 ../../libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer + (declare 'void drawGraph();' on top of file) diff --git a/tests/host/common/MockUDPSocket.cpp b/tests/host/common/MockUDPSocket.cpp index cd64f62e90..2b06e3f83c 100644 --- a/tests/host/common/MockUDPSocket.cpp +++ b/tests/host/common/MockUDPSocket.cpp @@ -21,6 +21,13 @@ int mockUDPSocket () 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 for udp port %d\n", port); + optval = 1; + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) + fprintf(stderr, MOCK "SO_REUSEADDR failed for udp port %d\n", port); + struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); From 964711e001269243b9d8335f059122f6a40bd74d Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Wed, 14 Nov 2018 17:47:49 +0100 Subject: [PATCH 18/50] WIP --- .../AdvancedWebServer/AdvancedWebServer.ino | 2 ++ tests/host/Makefile | 15 +++++++++------ tests/host/README | 7 ++++++- tests/host/common/HardwareSerial.cpp | 5 +++++ tests/host/common/MockEsp.cpp | 7 ++++++- tests/host/common/mock.h | 3 ++- tests/host/common/user_interface.cpp | 1 + 7 files changed, 31 insertions(+), 9 deletions(-) diff --git a/libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino b/libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino index 1315c9a30c..b19d120b32 100644 --- a/libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino +++ b/libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino @@ -40,6 +40,8 @@ ESP8266WebServer server(80); const int led = 13; +void drawGraph(); + void handleRoot() { digitalWrite(led, 1); char temp[400]; diff --git a/tests/host/Makefile b/tests/host/Makefile index abc9b50904..9965a37aed 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -21,10 +21,10 @@ CORE_CPP_FILES := $(addprefix $(CORE_PATH)/,\ WString.cpp \ Print.cpp \ FS.cpp \ - spiffs_api.cpp \ pgmspace.cpp \ MD5Builder.cpp \ ) +# spiffs_api.cpp \ CORE_C_FILES := $(addprefix $(CORE_PATH)/,\ core_esp8266_noniso.c \ @@ -189,8 +189,6 @@ ARDUINO_LIBS := \ ESP8266HTTPClient/src/ESP8266HTTPClient.cpp \ ) \ - - MOCK_ARDUINO_LIBS := \ common/MockClientContextSocket.cpp \ common/MockClientContext.cpp \ @@ -210,7 +208,12 @@ CPP_SOURCES_CORE_EMU = \ $(MOCK_ARDUINO_LIBS) \ $(ARDUINO_LIBS) \ -CPP_OBJECTS_CORE_EMU = $(CPP_SOURCES_CORE_EMU:.cpp=.cpp.o) + +ULIBPATHS = $(shell echo $(ULIBDIR) | sed 's,:, ,g') +USERLIBDIR = $(shell test -z "$(ULIBPATHS)" || for d in $(ULIBPATHS)/* $(ULIBPATHS)/*/src; do test -d $$d && echo -I$$d; done) +INC_PATHS += $(USERLIBDIR) + +CPP_OBJECTS_CORE_EMU = $(CPP_SOURCES_CORE_EMU:.cpp=.cpp.o) $(USERLIB:.cpp=.cpp.o) bin/fullcore.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE_EMU) ar -rcu $@ $^ @@ -219,9 +222,9 @@ bin/fullcore.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE_EMU) .PRECIOUS: %.cpp.o %: %.ino.cpp.o bin/fullcore.a $(CXX) $(LDFLAGS) $< bin/fullcore.a -o $@ - ln -sf ../$@ $(BINDIR) + test -r $@ && ln -sf ../$@ $(BINDIR) || ln -sf $@ $(BINDIR) -.PRECIOUS: %.cpp +.PRECIOUS: %.ino.cpp %.ino.cpp: %.ino @s=$<; \ n=$${s##*/}; \ diff --git a/tests/host/README b/tests/host/README index 06bc00e4e6..1f5c4cffbf 100644 --- a/tests/host/README +++ b/tests/host/README @@ -2,6 +2,8 @@ Host emulation (WIP) -------------------- +All results are stored or linked from ./bin/ . + Regular host test: make @@ -16,7 +18,6 @@ Build one example run it: ./bin/Blink -h - Interesting examples: make D=1 ../../libraries/esp8266/examples/Blink/Blink make D=1 ../../libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient @@ -25,3 +26,7 @@ Interesting examples: Needs tweaking: make D=1 ../../libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer (declare 'void drawGraph();' on top of file) + +Compile your sketches (remove the .ino part of the sketch file name): + make D=1 ULIBDIR=/path/to/your/arduino/libraries:/path/to/another/one /path/to/your/sketchdir/sketch + diff --git a/tests/host/common/HardwareSerial.cpp b/tests/host/common/HardwareSerial.cpp index 8a20caa684..89ef8b8999 100644 --- a/tests/host/common/HardwareSerial.cpp +++ b/tests/host/common/HardwareSerial.cpp @@ -17,6 +17,11 @@ void HardwareSerial::begin (unsigned long baud, SerialConfig config, SerialMode 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"); diff --git a/tests/host/common/MockEsp.cpp b/tests/host/common/MockEsp.cpp index e24a8d408f..019595b8ae 100644 --- a/tests/host/common/MockEsp.cpp +++ b/tests/host/common/MockEsp.cpp @@ -135,4 +135,9 @@ uint32_t EspClass::getFlashChipRealSize(void) uint32_t EspClass::getFlashChipSize(void) { return magicFlashChipSize(4); -} \ No newline at end of file +} + +String EspClass::getFullVersion () +{ + return "host-emulation"; +} diff --git a/tests/host/common/mock.h b/tests/host/common/mock.h index f9c455cdb6..062538e632 100644 --- a/tests/host/common/mock.h +++ b/tests/host/common/mock.h @@ -76,7 +76,8 @@ class InterruptLock { }; // -#define ESP8266 +#define ARDUINO 1 +#define ESP8266 1 #define A0 0 #define LED_BUILTIN 0 diff --git a/tests/host/common/user_interface.cpp b/tests/host/common/user_interface.cpp index b15cbf7fb7..9df9907e14 100644 --- a/tests/host/common/user_interface.cpp +++ b/tests/host/common/user_interface.cpp @@ -363,6 +363,7 @@ bool wifi_station_scan(struct scan_config *config, scan_done_cb_t cb) return false; } +uint32_t core_version = 1; /////////////////////////////////////// // not user_interface From 4b214867f97c67fa4e61b6fdf6262af47f72ddc9 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Wed, 14 Nov 2018 17:54:36 +0100 Subject: [PATCH 19/50] WIP --- .../CaptivePortalAdvanced.ino | 11 +++++++++++ tests/host/README | 16 +++++++--------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/libraries/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino b/libraries/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino index 8c662fd206..4ce62a5e60 100644 --- a/libraries/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino +++ b/libraries/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino @@ -5,6 +5,17 @@ #include #include +boolean isIp(String str); +String toStringIp(IPAddress ip); +void loadCredentials(); +void saveCredentials(); +void handleRoot(); +boolean captivePortal(); +void handleWifi(); +void handleWifiSave(); +void handleNotFound(); + + /* This example serves a "hello world" on a WLAN and a SoftAP at the same time. The SoftAP allow you to configure WLAN parameters at run time. They are not setup in the sketch but saved on EEPROM. diff --git a/tests/host/README b/tests/host/README index 1f5c4cffbf..41b11ab3d8 100644 --- a/tests/host/README +++ b/tests/host/README @@ -7,7 +7,7 @@ All results are stored or linked from ./bin/ . Regular host test: make -Build all examples with debug enabled: (WIP) +Build all examples with debug enabled (D=1): (WIP) make D=1 examples Show the example list: @@ -18,15 +18,13 @@ Build one example run it: ./bin/Blink -h -Interesting examples: +Non exhaustive list of working examples: make D=1 ../../libraries/esp8266/examples/Blink/Blink make D=1 ../../libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient make D=1 ../../libraries/ESP8266WebServer/examples/HelloServer/HelloServer - -Needs tweaking: make D=1 ../../libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer - (declare 'void drawGraph();' on top of file) - -Compile your sketches (remove the .ino part of the sketch file name): - make D=1 ULIBDIR=/path/to/your/arduino/libraries:/path/to/another/one /path/to/your/sketchdir/sketch - + + TO CHECK: mDNS is implemented, receive and sends UDP packets + +Compile your sketches (remove the '.ino' part of the sketch file name): + make D=1 ULIBDIR=/path/to/your/arduino/libraries:/path/to/another/one /path/to/your/sketchdir/sketch/sketch From 89219873d99a6cac50511c76721596df316b46c5 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Wed, 14 Nov 2018 19:13:53 +0100 Subject: [PATCH 20/50] WIP mcast receiving, not sending --- libraries/ESP8266WiFi/examples/udp/udp.ino | 116 +++++++++++++++++++++ tests/host/common/ArduinoMain.cpp | 16 ++- tests/host/common/MockUDPSocket.cpp | 58 ++++++----- tests/host/common/mock.h | 12 +-- tests/host/common/user_interface.cpp | 15 ++- 5 files changed, 178 insertions(+), 39 deletions(-) create mode 100644 libraries/ESP8266WiFi/examples/udp/udp.ino diff --git a/libraries/ESP8266WiFi/examples/udp/udp.ino b/libraries/ESP8266WiFi/examples/udp/udp.ino new file mode 100644 index 0000000000..9a6cc6fd98 --- /dev/null +++ b/libraries/ESP8266WiFi/examples/udp/udp.ino @@ -0,0 +1,116 @@ +/* + 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 +*/ + + +#include + +//#define UDP_TX_PACKET_MAX_SIZE 1024 + +// Enter a MAC address and IP address for your controller below. +// The IP address will be dependent on your local network: +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +}; +IPAddress ip(192, 168, 1, 177); + +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 + +// An EthernetUDP instance to let us send and receive packets over UDP +WiFiUDP Udp; + +void setup() { + // start the Ethernet and UDP: + Udp.begin(localPort); + + Serial.begin(9600); +} + +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); +} + + +/* + Processing sketch to run with this example + ===================================================== + + // Processing UDP example to send and receive string data from Arduino + // press any key to send the "Hello Arduino" message + + + import hypermedia.net.*; + + UDP udp; // define the UDP object + + + void setup() { + udp = new UDP( this, 6000 ); // create a new datagram connection on port 6000 + //udp.log( true ); // <-- printout the connection activity + udp.listen( true ); // and wait for incoming message + } + + void draw() + { + } + + void keyPressed() { + String ip = "192.168.1.177"; // the remote IP address + int port = 8888; // the destination port + + udp.send("Hello World", ip, port ); // the message to send + + } + + void receive( byte[] data ) { // <-- default handler + //void receive( byte[] data, String ip, int port ) { // <-- extended handler + + for(int i=0; i < data.length; i++) + print(char(data[i])); + println(); + } +*/ + + diff --git a/tests/host/common/ArduinoMain.cpp b/tests/host/common/ArduinoMain.cpp index 6956a59497..fb3674faa0 100644 --- a/tests/host/common/ArduinoMain.cpp +++ b/tests/host/common/ArduinoMain.cpp @@ -1,5 +1,6 @@ #include +#include // wifi_get_ip_info() #include #include "lwip/opt.h" @@ -33,7 +34,8 @@ void help (const char* argv0, int exitcode) "%s - compiled with esp8266/arduino emulator\n" "options:\n" " -h\n" - " -i \n" + " -i - use this interface for IP address\n" + " -l - bind tcp/udp servers to interface only (not 0.0.0.0)\n" ,argv0); exit(exitcode); } @@ -41,6 +43,7 @@ void help (const char* argv0, int exitcode) static struct option options[] = { { "help", no_argument, NULL, 'h' }, + { "local", required_argument, NULL, 'l' }, { "interface", required_argument, NULL, 'i' }, }; @@ -48,7 +51,7 @@ int main (int argc, char* const argv []) { for (;;) { - int n = getopt_long(argc, argv, "hi:", options, NULL); + int n = getopt_long(argc, argv, "hli:", options, NULL); if (n < 0) break; switch (n) @@ -59,8 +62,17 @@ int main (int argc, char* const argv []) case 'i': host_interface = optarg; break; + case 'l': + global_ipv4_netfmt = NO_GLOBAL_BINDING; + 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) diff --git a/tests/host/common/MockUDPSocket.cpp b/tests/host/common/MockUDPSocket.cpp index 2b06e3f83c..e7000ca3ae 100644 --- a/tests/host/common/MockUDPSocket.cpp +++ b/tests/host/common/MockUDPSocket.cpp @@ -23,23 +23,24 @@ 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 for udp port %d\n", port); + 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 for udp port %d\n", port); + 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 = dstaddr; + //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 to port %d failed: %s\n", port, strerror(errno)); + fprintf(stderr, MOCK "UDP bind on port %d failed: %s\n", port, strerror(errno)); return false; } else @@ -48,9 +49,20 @@ bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast) 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 = 0;//htonl(INADDR_ANY); + //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); @@ -136,33 +148,23 @@ size_t mockUDPRead (int sock, char* dst, size_t size, int timeout_ms, char* ccin size_t mockUDPWrite (int sock, const uint8_t* data, size_t size, int timeout_ms, uint32_t ipv4, uint16_t port) { - struct pollfd p; - p.fd = sock; - p.events = POLLOUT; - int ret = poll(&p, 1, timeout_ms); + // 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); +fprintf(stderr, MOCK "------------------> UDP send %d bytes on sock=%d\n", (int)size, sock); + int ret = ::sendto(sock, data, size, 0/*flags*/, (const sockaddr*)&peer, sizeof(peer)); if (ret == -1) { - fprintf(stderr, MOCK "UDPContext::write: poll(%d): %s\n", sock, strerror(errno)); - return 0; + fprintf(stderr, MOCK "UDPContext::write: write(%d): %s\n", sock, strerror(errno)); + return 0; } - if (ret) + if (ret != (int)size) { - // 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); - 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 < %d) (TODO)\n", (int)ret, (int)size); - exit(EXIT_FAILURE); - } + fprintf(stderr, MOCK "UDPContext::write: short write (%d < %d) (TODO)\n", (int)ret, (int)size); + exit(EXIT_FAILURE); } + return ret; } diff --git a/tests/host/common/mock.h b/tests/host/common/mock.h index 062538e632..f11070f9a7 100644 --- a/tests/host/common/mock.h +++ b/tests/host/common/mock.h @@ -18,16 +18,13 @@ typedef uint32_t uint32; // -// htontoh code in common/MockTools.cpp -#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS - -// - #include #define RANDOM_REG32 ((uint32_t)random()) -// +// net tweak +// htontoh code in common/MockTools.cpp +#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS #undef INADDR_NONE // @@ -40,6 +37,9 @@ int ets_printf (const char* fmt, ...) __attribute__ ((format (printf, 1, 2))); 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 diff --git a/tests/host/common/user_interface.cpp b/tests/host/common/user_interface.cpp index 9df9907e14..a3fa9bbb8a 100644 --- a/tests/host/common/user_interface.cpp +++ b/tests/host/common/user_interface.cpp @@ -81,6 +81,8 @@ 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; @@ -119,12 +121,19 @@ bool wifi_get_ip_info (uint8 if_index, struct ip_info *info) if (ifAddrStruct != NULL) freeifaddrs(ifAddrStruct); + (void)if_index; //if (if_index != STATION_IF) // fprintf(stderr, "we are not AP"); - info->ip.addr = ipv4; - info->netmask.addr = mask; - info->gw.addr = ipv4; + 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; } From f99e2729575dc50cb0270174aea1edfbb571b9a1 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Wed, 14 Nov 2018 23:15:48 +0100 Subject: [PATCH 21/50] WIP mdns OK --- libraries/ESP8266WiFi/examples/udp/udp.ino | 27 ++++---- tests/host/README | 7 +-- tests/host/common/MockUDPSocket.cpp | 1 - tests/host/common/include/UdpContext.h | 72 +++++++++++----------- 4 files changed, 53 insertions(+), 54 deletions(-) diff --git a/libraries/ESP8266WiFi/examples/udp/udp.ino b/libraries/ESP8266WiFi/examples/udp/udp.ino index 9a6cc6fd98..fb3cb7d911 100644 --- a/libraries/ESP8266WiFi/examples/udp/udp.ino +++ b/libraries/ESP8266WiFi/examples/udp/udp.ino @@ -11,20 +11,15 @@ This code is in the public domain. - adapted from Ethernet library + adapted from Ethernet library examples */ +#include #include -//#define UDP_TX_PACKET_MAX_SIZE 1024 - -// Enter a MAC address and IP address for your controller below. -// The IP address will be dependent on your local network: -byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED -}; -IPAddress ip(192, 168, 1, 177); +#define SSID "ssid" +#define PSK "psk" unsigned int localPort = 8888; // local port to listen on @@ -32,14 +27,20 @@ unsigned int localPort = 8888; // local port to listen on char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet, char ReplyBuffer[] = "acknowledged\r\n"; // a string to send back -// An EthernetUDP instance to let us send and receive packets over UDP WiFiUDP Udp; void setup() { - // start the Ethernet and UDP: + 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); - - Serial.begin(9600); } void loop() { diff --git a/tests/host/README b/tests/host/README index 41b11ab3d8..a68dafa617 100644 --- a/tests/host/README +++ b/tests/host/README @@ -19,12 +19,11 @@ run it: ./bin/Blink -h Non exhaustive list of working examples: - make D=1 ../../libraries/esp8266/examples/Blink/Blink + 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 - TO CHECK: mDNS is implemented, receive and sends UDP packets - -Compile your sketches (remove the '.ino' part of the sketch file name): +Compile your own sketches (remove the '.ino' part of the sketch file name): make D=1 ULIBDIR=/path/to/your/arduino/libraries:/path/to/another/one /path/to/your/sketchdir/sketch/sketch diff --git a/tests/host/common/MockUDPSocket.cpp b/tests/host/common/MockUDPSocket.cpp index e7000ca3ae..d7d9f8618a 100644 --- a/tests/host/common/MockUDPSocket.cpp +++ b/tests/host/common/MockUDPSocket.cpp @@ -153,7 +153,6 @@ size_t mockUDPWrite (int sock, const uint8_t* data, size_t size, int timeout_ms, peer.sin_family = AF_INET; peer.sin_addr.s_addr = ipv4; //XXFIXME should use lwip_htonl? peer.sin_port = htons(port); -fprintf(stderr, MOCK "------------------> UDP send %d bytes on sock=%d\n", (int)size, sock); int ret = ::sendto(sock, data, size, 0/*flags*/, (const sockaddr*)&peer, sizeof(peer)); if (ret == -1) { diff --git a/tests/host/common/include/UdpContext.h b/tests/host/common/include/UdpContext.h index f803e95f08..51a66c99b1 100644 --- a/tests/host/common/include/UdpContext.h +++ b/tests/host/common/include/UdpContext.h @@ -81,13 +81,13 @@ class UdpContext void setMulticastInterface(const ip_addr_t& addr) { - // not needed on posix, multicast is associated with - // socket and its address (0.0.0.0) = all interfaces + // 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"); + //fprintf(stderr, MOCK "TODO: UdpContext::setMulticastTTL\n"); } // warning: handler is called from tcp stack context @@ -98,7 +98,7 @@ class UdpContext size_t getSize() { - return _inbufsize; + return _inbufsize; } size_t tell() const @@ -108,7 +108,7 @@ class UdpContext void seek(const size_t pos) { - fprintf(stderr, MOCK "TODO: implement UDP offset\n"); + fprintf(stderr, MOCK "TODO: implement UDP offset\n"); if (!isValidOffset(pos)) { fprintf(stderr, MOCK "UDPContext::seek too far (%d >= %d)\n", (int)pos, (int)_inbufsize); @@ -132,26 +132,26 @@ class UdpContext uint32_t getDestAddress() { - fprintf(stderr, MOCK "TODO: implement UDP getDestAddress\n"); + 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; // + 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; + mockUDPFillInBuf(_sock, _inbuf, _inbufsize, addrsize, addr, _dstport); + if (_inbufsize > 0) + { + translate_addr(); + return true; + } + return false; } int read() @@ -173,37 +173,37 @@ class UdpContext void flush() { - //fprintf(stderr, MOCK "UdpContext::flush() does not follow arduino's flush concept\n"); - //exit(EXIT_FAILURE); - // would be: + //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 -> %d)\n", CCBUFSIZE, (int)(size + _outbufsize)); - exit(EXIT_FAILURE); - } - - memcpy(_outbuf + _outbufsize, data, size); - _outbufsize += size; - return size; + if (size + _outbufsize > sizeof _outbuf) + { + fprintf(stderr, MOCK "UdpContext::append: increase CCBUFSIZE (%d -> %d)\n", CCBUFSIZE, (int)(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; + 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(); + if (_on_rx) _on_rx(); } public: @@ -240,9 +240,9 @@ class UdpContext inline err_t igmp_joingroup (const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr) { - (void)ifaddr; - UdpContext::staticMCastAddr = groupaddr->addr; - return ERR_OK; + (void)ifaddr; + UdpContext::staticMCastAddr = groupaddr->addr; + return ERR_OK; } #endif//UDPCONTEXT_H From 669397eb28fd776858e5af47a6513f81dfd0c906 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Wed, 14 Nov 2018 23:32:27 +0100 Subject: [PATCH 22/50] beta version --- tests/host/common/mock.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/host/common/mock.h b/tests/host/common/mock.h index f11070f9a7..689f468792 100644 --- a/tests/host/common/mock.h +++ b/tests/host/common/mock.h @@ -76,10 +76,11 @@ class InterruptLock { }; // -#define ARDUINO 1 +#define ARDUINO 267 #define ESP8266 1 #define A0 0 #define LED_BUILTIN 0 +#define F_CPU 80000000 // From 2ec3403c7e2d63bdaae8de9084f7204b148618ca Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Thu, 15 Nov 2018 16:41:57 +0100 Subject: [PATCH 23/50] SSL + doc --- .../src/WiFiClientSecureBearSSL.cpp | 14 ++- tests/host/Makefile | 55 ++++++++--- tests/host/README | 29 ------ tests/host/README.txt | 93 +++++++++++++++++++ tests/host/common/MockEsp.cpp | 10 ++ tests/host/common/MockTools.cpp | 10 ++ tests/host/common/mock.h | 3 +- tools/sdk/ssl/Makefile | 5 +- 8 files changed, 173 insertions(+), 46 deletions(-) delete mode 100644 tests/host/README create mode 100644 tests/host/README.txt diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp index 99a271b3d7..327bebe8a6 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp @@ -1389,6 +1389,17 @@ bool WiFiClientSecure::loadPrivateKey(Stream& stream, size_t size) { extern "C" { extern size_t br_esp8266_stack_proxy_usage(); +#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 void _BearSSLCheckStack(const char *fcn, const char *file, int line) { static int cnt = 0; register uint32_t *sp asm("a1"); @@ -1396,7 +1407,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=%d, FREEHEAP=%d\n", file, fcn, line, freestack, (int)br_esp8266_stack_proxy_usage(), freeheap); if (freestack < 256) { Serial.printf("!!! Out of main stack space\n"); } @@ -1414,6 +1425,7 @@ extern "C" { cnt++; } } +#endif void _BearSSLSerialPrint(const char *str) { static int cnt = 0; diff --git a/tests/host/Makefile b/tests/host/Makefile index 9965a37aed..490638f201 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -107,12 +107,14 @@ 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 +clean: clean-objects clean-coverage # clean everything rm -rf $(BINDIR) clean-objects: @@ -121,7 +123,7 @@ clean-objects: 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) @@ -131,7 +133,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 @@ -176,6 +178,10 @@ ARDUINO_LIBS := \ ESP8266WiFiScan.cpp \ WiFiClient.cpp \ WiFiUdp.cpp \ + WiFiClientSecureBearSSL.cpp \ + WiFiServerSecureBearSSL.cpp \ + BearSSLHelpers.cpp \ + CertStoreBearSSL.cpp \ ) \ $(addprefix ESP8266WebServer/src/,\ ESP8266WebServer.cpp \ @@ -209,9 +215,18 @@ CPP_SOURCES_CORE_EMU = \ $(ARDUINO_LIBS) \ -ULIBPATHS = $(shell echo $(ULIBDIR) | sed 's,:, ,g') -USERLIBDIR = $(shell test -z "$(ULIBPATHS)" || for d in $(ULIBPATHS)/* $(ULIBPATHS)/*/src; do test -d $$d && echo -I$$d; done) -INC_PATHS += $(USERLIBDIR) +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 "WARNING: '$$dd' is not a directory" 1>&2; done; done) +INC_PATHS += $(USERLIBDIRS) + +LIBSSLFILE = ../../tools/sdk/ssl/bearssl/build/libbearssl.a +ifeq (,$(wildcard $(LIBSSLFILE))) +LIBSSL = +else +LIBSSL = $(LIBSSLFILE) +endif +ssl: # download source and build BearSSL + cd ../../tools/sdk/ssl && make native CPP_OBJECTS_CORE_EMU = $(CPP_SOURCES_CORE_EMU:.cpp=.cpp.o) $(USERLIB:.cpp=.cpp.o) @@ -221,7 +236,7 @@ bin/fullcore.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE_EMU) .PRECIOUS: %.cpp.o %: %.ino.cpp.o bin/fullcore.a - $(CXX) $(LDFLAGS) $< bin/fullcore.a -o $@ + $(CXX) $(LDFLAGS) $< bin/fullcore.a $(LIBSSL) -o $@ test -r $@ && ln -sf ../$@ $(BINDIR) || ln -sf $@ $(BINDIR) .PRECIOUS: %.ino.cpp @@ -240,8 +255,7 @@ bin/fullcore.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE_EMU) -include $(BINDIR)/Makefile.inc.ino .PHONY: list -list: - # copy examples locally +list: # show core example list @for dir in ../../libraries/*/examples; do \ exampledir=$${dir%/*}; \ exampledirname=$${exampledir##*/}; \ @@ -252,8 +266,7 @@ list: done; \ $(BINDIR)/Makefile.inc.ino: - # copy examples locally - all=""; \ + @all=""; \ for dir in ../../libraries/*/examples; do \ exampledir=$${dir%/*}; \ exampledirname=$${exampledir##*/}; \ @@ -264,5 +277,19 @@ $(BINDIR)/Makefile.inc.ino: done; \ echo "examples: $$all" > $@ -examples: $(BINDIR)/Makefile.inc.ino +examples: $(BINDIR)/Makefile.inc.ino # build all core examples $(MAKE) $@ + +################################################# +# help + +MAKEFILE = $(word 1, $(MAKEFILE_LIST)) + +.PHONY: help +help: + @cat README.txt + @echo "" + @echo "Make rules:" + @echo "" + @sed -rne 's,([^: \t]*):[^=#]*#[\t ]*(.*),\1 - \2,p' $(MAKEFILE) + @echo "" diff --git a/tests/host/README b/tests/host/README deleted file mode 100644 index a68dafa617..0000000000 --- a/tests/host/README +++ /dev/null @@ -1,29 +0,0 @@ - -Host emulation (WIP) --------------------- - -All results are stored or linked from ./bin/ . - -Regular host test: - make - -Build all examples with debug enabled (D=1): (WIP) - make D=1 examples - -Show the example list: - make list - -Build one example - make D=1 ../../libraries/esp8266/examples/Blink/Blink -run it: - ./bin/Blink -h - -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 - -Compile your own sketches (remove the '.ino' part of the sketch file name): - make D=1 ULIBDIR=/path/to/your/arduino/libraries:/path/to/another/one /path/to/your/sketchdir/sketch/sketch diff --git a/tests/host/README.txt b/tests/host/README.txt new file mode 100644 index 0000000000..161645dc06 --- /dev/null +++ b/tests/host/README.txt @@ -0,0 +1,93 @@ + +Host Tests for Continuous Integration +------------------------------------- + + make CI + + +Host emulation (WIP) +-------------------- + +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. + +Cuurrently 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 a sketch +----------------------- + +All results are stored or linked from ./bin/ . + +Show the core example list: + make list + + +Build one example + make D=1 ../../libraries/esp8266/examples/Blink/Blink +run it: + ./bin/Blink -h + + +Optionnal 'D=1' enables core debug. + + +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 + + +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): + + make D=1 ULIBDIRS=/path/to/your/arduino/libraries:/path/to/another/one /path/to/your/sketchdir/sketch/sketch + or + ULIBDIRS=/path/to/your/arduino/libraries:/path/to/another/one make D=1 /path/to/your/sketchdir/sketch/sketch + or + export ULIBDIRS=/path/to/your/arduino/libraries:/path/to/another/one + make D=1 /path/to/your/sketchdir/sketch/sketch + + +Build all examples with debug enabled (D=1): (not fully working yet) + make D=1 examples + + +Running a sketch +---------------- + +- SPIFFS + (already done, to check) + +- SDCARD + (TODO) + +- EEPROM + (to check) a file named 'eeprom' is created in current directory for reading and writing. + +- Serial: + for now Serial.read() returns -1. Serial.write() will printf(). + +- GPIOs + read as 0(digital) or 512(analog). + output is printed on console. + +Once a sketch is compiled, just run it: + /path/to/your/sketchdir/sketch/sketch + +Options are available: + -h + -i eth0 bind servers to this interface (WIP) + -l bind Multicast to the above interface (WIP) + +TODO +---- +A lot. +Make fun, propose PRs. diff --git a/tests/host/common/MockEsp.cpp b/tests/host/common/MockEsp.cpp index 019595b8ae..ea100fab04 100644 --- a/tests/host/common/MockEsp.cpp +++ b/tests/host/common/MockEsp.cpp @@ -141,3 +141,13 @@ String EspClass::getFullVersion () { return "host-emulation"; } + +uint32_t EspClass::getFreeContStack() +{ + return 4000; +} + +void EspClass::resetFreeContStack() +{ +} + diff --git a/tests/host/common/MockTools.cpp b/tests/host/common/MockTools.cpp index 123552cf58..01932390e9 100644 --- a/tests/host/common/MockTools.cpp +++ b/tests/host/common/MockTools.cpp @@ -22,4 +22,14 @@ int ets_printf (const char* fmt, ...) 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=%dH offset=%dS) (time will be host's)\n", (int)timezone, daylightOffset_sec); +} + }; diff --git a/tests/host/common/mock.h b/tests/host/common/mock.h index 689f468792..4162069873 100644 --- a/tests/host/common/mock.h +++ b/tests/host/common/mock.h @@ -61,7 +61,6 @@ size_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms int serverAccept (int sock); // udp -#define ADDRBUFSIZE 32 // ipv6:16 ipv4:4 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); @@ -76,6 +75,8 @@ class InterruptLock { }; // +#define CORE_MOCK 1 + #define ARDUINO 267 #define ESP8266 1 #define A0 0 diff --git a/tools/sdk/ssl/Makefile b/tools/sdk/ssl/Makefile index bc9126f9ff..4be4efa974 100644 --- a/tools/sdk/ssl/Makefile +++ b/tools/sdk/ssl/Makefile @@ -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,6 @@ 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 From e4a6c376d815e891a8b4fddbfed2a148f85087cd Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Thu, 15 Nov 2018 17:06:35 +0100 Subject: [PATCH 24/50] update travis host test command --- tests/common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/common.sh b/tests/common.sh index c9e48309e2..8deb65d5a1 100755 --- a/tests/common.sh +++ b/tests/common.sh @@ -134,7 +134,7 @@ function build_docs() function run_host_tests() { pushd host - make + make CI make clean-objects popd } From 37aaa365a24dcfdd4a4bb59876624ec97dddb73c Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Thu, 15 Nov 2018 17:33:46 +0100 Subject: [PATCH 25/50] licenses --- tests/host/Makefile | 10 ++---- tests/host/README | 2 +- tests/host/common/ArduinoMain.cpp | 30 +++++++++++++++++ tests/host/common/ArduinoWire.cpp | 30 +++++++++++++++++ tests/host/common/EEPROM.h | 30 +++++++++++++++++ tests/host/common/HardwareSerial.cpp | 30 +++++++++++++++++ tests/host/common/MockClientContext.cpp | 30 +++++++++++++++++ tests/host/common/MockClientContextSocket.cpp | 30 +++++++++++++++++ tests/host/common/MockEEPROM.cpp | 30 +++++++++++++++++ tests/host/common/MockEsp.cpp | 30 +++++++++++++++++ tests/host/common/MockSPI.cpp | 30 +++++++++++++++++ tests/host/common/MockTools.cpp | 30 +++++++++++++++++ tests/host/common/MockUDPSocket.cpp | 30 +++++++++++++++++ tests/host/common/MockWiFiServer.cpp | 31 ++++++++++++++++- tests/host/common/MockWiFiServerSocket.cpp | 30 +++++++++++++++++ tests/host/common/include/ClientContext.h | 18 ++++++++++ tests/host/common/include/UdpContext.h | 2 +- tests/host/common/mock.h | 33 +++++++++++++++++++ tests/host/common/user_interface.cpp | 30 +++++++++++++++++ 19 files changed, 476 insertions(+), 10 deletions(-) diff --git a/tests/host/Makefile b/tests/host/Makefile index 9965a37aed..abbe583641 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -65,10 +65,9 @@ INC_PATHS := $(addprefix -I,\ ../../tools/sdk/include \ ) -INC_PATHS += -DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 \ - $(addprefix -I,\ - ../../tools/sdk/lwip2/include \ - ) +INC_PATHS += $(addprefix -I,\ + ../../tools/sdk/lwip2/include \ +) TEST_CPP_FILES := \ fs/test_fs.cpp \ @@ -201,7 +200,6 @@ MOCK_ARDUINO_LIBS := \ common/MockEEPROM.cpp \ common/MockSPI.cpp \ -ARDUINO_LIBS += CPP_SOURCES_CORE_EMU = \ $(MOCK_CPP_FILES_EMU) \ $(CORE_CPP_FILES) \ @@ -241,7 +239,6 @@ bin/fullcore.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE_EMU) .PHONY: list list: - # copy examples locally @for dir in ../../libraries/*/examples; do \ exampledir=$${dir%/*}; \ exampledirname=$${exampledir##*/}; \ @@ -252,7 +249,6 @@ list: done; \ $(BINDIR)/Makefile.inc.ino: - # copy examples locally all=""; \ for dir in ../../libraries/*/examples; do \ exampledir=$${dir%/*}; \ diff --git a/tests/host/README b/tests/host/README index a68dafa617..85a22d15c7 100644 --- a/tests/host/README +++ b/tests/host/README @@ -24,6 +24,6 @@ Non exhaustive list of working examples: 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 - + Compile your own sketches (remove the '.ino' part of the sketch file name): make D=1 ULIBDIR=/path/to/your/arduino/libraries:/path/to/another/one /path/to/your/sketchdir/sketch/sketch diff --git a/tests/host/common/ArduinoMain.cpp b/tests/host/common/ArduinoMain.cpp index fb3674faa0..320b160077 100644 --- a/tests/host/common/ArduinoMain.cpp +++ b/tests/host/common/ArduinoMain.cpp @@ -1,3 +1,33 @@ +/* + 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 #include // wifi_get_ip_info() diff --git a/tests/host/common/ArduinoWire.cpp b/tests/host/common/ArduinoWire.cpp index 24efbf31c0..3d82cc7959 100644 --- a/tests/host/common/ArduinoWire.cpp +++ b/tests/host/common/ArduinoWire.cpp @@ -1,3 +1,33 @@ +/* + 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 diff --git a/tests/host/common/EEPROM.h b/tests/host/common/EEPROM.h index 0a72f75ee9..a1e47546de 100644 --- a/tests/host/common/EEPROM.h +++ b/tests/host/common/EEPROM.h @@ -1,3 +1,33 @@ +/* + 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 diff --git a/tests/host/common/HardwareSerial.cpp b/tests/host/common/HardwareSerial.cpp index 89ef8b8999..4aa097a0cd 100644 --- a/tests/host/common/HardwareSerial.cpp +++ b/tests/host/common/HardwareSerial.cpp @@ -1,3 +1,33 @@ +/* + 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 diff --git a/tests/host/common/MockClientContext.cpp b/tests/host/common/MockClientContext.cpp index 47463218e7..ccc06b56d9 100644 --- a/tests/host/common/MockClientContext.cpp +++ b/tests/host/common/MockClientContext.cpp @@ -1,3 +1,33 @@ +/* + 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 #include diff --git a/tests/host/common/MockClientContextSocket.cpp b/tests/host/common/MockClientContextSocket.cpp index 09e085ba41..533d468f5f 100644 --- a/tests/host/common/MockClientContextSocket.cpp +++ b/tests/host/common/MockClientContextSocket.cpp @@ -1,4 +1,34 @@ +/* + 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 diff --git a/tests/host/common/MockEEPROM.cpp b/tests/host/common/MockEEPROM.cpp index cfc01ff995..0f882ca0bd 100644 --- a/tests/host/common/MockEEPROM.cpp +++ b/tests/host/common/MockEEPROM.cpp @@ -1,3 +1,33 @@ +/* + 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 diff --git a/tests/host/common/MockEsp.cpp b/tests/host/common/MockEsp.cpp index 019595b8ae..c08b9cb0e7 100644 --- a/tests/host/common/MockEsp.cpp +++ b/tests/host/common/MockEsp.cpp @@ -1,3 +1,33 @@ +/* + 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 #include diff --git a/tests/host/common/MockSPI.cpp b/tests/host/common/MockSPI.cpp index 1409612f41..251cad914a 100644 --- a/tests/host/common/MockSPI.cpp +++ b/tests/host/common/MockSPI.cpp @@ -1,3 +1,33 @@ +/* + 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 diff --git a/tests/host/common/MockTools.cpp b/tests/host/common/MockTools.cpp index 123552cf58..d5e0c7fcf4 100644 --- a/tests/host/common/MockTools.cpp +++ b/tests/host/common/MockTools.cpp @@ -1,3 +1,33 @@ +/* + 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 #include diff --git a/tests/host/common/MockUDPSocket.cpp b/tests/host/common/MockUDPSocket.cpp index d7d9f8618a..017b0cb769 100644 --- a/tests/host/common/MockUDPSocket.cpp +++ b/tests/host/common/MockUDPSocket.cpp @@ -1,3 +1,33 @@ +/* + 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 #include diff --git a/tests/host/common/MockWiFiServer.cpp b/tests/host/common/MockWiFiServer.cpp index 31c13e1db3..0150e436ec 100644 --- a/tests/host/common/MockWiFiServer.cpp +++ b/tests/host/common/MockWiFiServer.cpp @@ -1,3 +1,33 @@ +/* + 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 #include @@ -14,7 +44,6 @@ extern "C" const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY); WiFiServer::WiFiServer (IPAddress addr, uint16_t port) { -//XXX factorize (void)addr; if (port < 1024) { diff --git a/tests/host/common/MockWiFiServerSocket.cpp b/tests/host/common/MockWiFiServerSocket.cpp index 769c14238f..7c9a0333db 100644 --- a/tests/host/common/MockWiFiServerSocket.cpp +++ b/tests/host/common/MockWiFiServerSocket.cpp @@ -1,3 +1,33 @@ +/* + 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 diff --git a/tests/host/common/include/ClientContext.h b/tests/host/common/include/ClientContext.h index 817d2b6387..ee88258431 100644 --- a/tests/host/common/include/ClientContext.h +++ b/tests/host/common/include/ClientContext.h @@ -1,4 +1,22 @@ /* + 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 diff --git a/tests/host/common/include/UdpContext.h b/tests/host/common/include/UdpContext.h index 51a66c99b1..7e9c279952 100644 --- a/tests/host/common/include/UdpContext.h +++ b/tests/host/common/include/UdpContext.h @@ -1,5 +1,5 @@ /* - UdpContext.h - UDP connection handling on top of lwIP + 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. diff --git a/tests/host/common/mock.h b/tests/host/common/mock.h index 689f468792..ebd59fe494 100644 --- a/tests/host/common/mock.h +++ b/tests/host/common/mock.h @@ -1,3 +1,33 @@ +/* + 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 @@ -81,6 +111,9 @@ class InterruptLock { }; #define A0 0 #define LED_BUILTIN 0 #define F_CPU 80000000 +#define LWIP_OPEN_SRC +#define TCP_MSS 536 +#define LWIP_FEATURES 1 // diff --git a/tests/host/common/user_interface.cpp b/tests/host/common/user_interface.cpp index a3fa9bbb8a..42bafb3fc4 100644 --- a/tests/host/common/user_interface.cpp +++ b/tests/host/common/user_interface.cpp @@ -1,3 +1,33 @@ +/* + 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 From 98f4ccada958e3435d0633e000b4cc956e60a918 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Thu, 15 Nov 2018 17:36:59 +0100 Subject: [PATCH 26/50] typo --- tests/host/README.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/host/README.txt b/tests/host/README.txt index 161645dc06..8f147bb5ac 100644 --- a/tests/host/README.txt +++ b/tests/host/README.txt @@ -13,7 +13,7 @@ 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. -Cuurrently network emulation is a complete rewrite of +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. From 81c4f9b2277028b942f54a1dd287c61e5cba53ec Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Thu, 15 Nov 2018 17:53:09 +0100 Subject: [PATCH 27/50] doc: arduino builder is not around: declare functions before calling them --- tests/host/README.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/host/README.txt b/tests/host/README.txt index 8f147bb5ac..633750c56e 100644 --- a/tests/host/README.txt +++ b/tests/host/README.txt @@ -33,7 +33,7 @@ run it: ./bin/Blink -h -Optionnal 'D=1' enables core debug. +Optional 'D=1' enables core debug. Non exhaustive list of working examples: @@ -47,6 +47,7 @@ Non exhaustive list of working examples: 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:/path/to/another/one /path/to/your/sketchdir/sketch/sketch or From 76c7c4b6daa09e82c3620f47fd421407760ca5e4 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Thu, 15 Nov 2018 23:03:33 +0100 Subject: [PATCH 28/50] fix with latest SSL PR, compile in 32 bits mode --- libraries/ESP8266WiFi/src/BearSSLHelpers.cpp | 4 ++++ .../ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp | 15 ++++++++++++--- tests/host/Makefile | 10 +++++----- tests/host/README.txt | 2 +- tests/host/common/ArduinoMain.cpp | 16 ++++++++++++---- tests/host/common/MockTools.cpp | 14 ++++++++++++++ tools/sdk/ssl/Makefile | 3 +++ 7 files changed, 51 insertions(+), 13 deletions(-) diff --git a/libraries/ESP8266WiFi/src/BearSSLHelpers.cpp b/libraries/ESP8266WiFi/src/BearSSLHelpers.cpp index 16cf99f3b1..024938d213 100644 --- a/libraries/ESP8266WiFi/src/BearSSLHelpers.cpp +++ b/libraries/ESP8266WiFi/src/BearSSLHelpers.cpp @@ -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 + }; \ No newline at end of file diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp index 91133e77c3..ab21d9509b 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp @@ -44,6 +44,8 @@ extern "C" { #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,9 +1381,9 @@ bool WiFiClientSecure::loadPrivateKey(Stream& stream, size_t size) { // SSL debugging which should focus on the WiFiClientBearSSL objects. extern "C" { - extern size_t br_esp8266_stack_proxy_usage(); #if CORE_MOCK + void br_esp8266_stack_proxy_init(uint8_t *space, uint16_t size) { (void)space; (void)size; @@ -1389,7 +1393,11 @@ extern "C" { (void)file; (void)line; } -#else + +#else // !CORE_MOCK + + extern size_t br_esp8266_stack_proxy_usage(); + void _BearSSLCheckStack(const char *fcn, const char *file, int line) { static int cnt = 0; register uint32_t *sp asm("a1"); @@ -1415,7 +1423,8 @@ extern "C" { cnt++; } } -#endif + +#endif // !CORE_MOCK void _BearSSLSerialPrint(const char *str) { static int cnt = 0; diff --git a/tests/host/Makefile b/tests/host/Makefile index dd7b7cb9f2..60da21b6ce 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -84,9 +84,9 @@ 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 -O0 -fno-common -g -CFLAGS += -std=c99 -Wall -Werror -coverage -O0 -fno-common -g -LDFLAGS += -coverage -O0 -g +CXXFLAGS += $(DEBUG) -std=c++11 -Wall -Werror -coverage -O0 -fno-common -g -m32 +CFLAGS += -std=c99 -Wall -Werror -coverage -O0 -fno-common -g -m32 +LDFLAGS += -coverage -O0 -g -m32 VALGRINDFLAGS += --leak-check=full --track-origins=yes --error-limit=no --show-leak-kinds=all --error-exitcode=999 # CXXFLAGS += -Wno-nonnull-compare # libraries/ESP8266WiFi/src/include/UdpContext.h:85:9: error: nonnull argument ‘this’ compared to NULL [-Werror=nonnull-compare] -- (if(this != 0)) @@ -217,14 +217,14 @@ 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 "WARNING: '$$dd' is not a directory" 1>&2; done; done) INC_PATHS += $(USERLIBDIRS) -LIBSSLFILE = ../../tools/sdk/ssl/bearssl/build/libbearssl.a +LIBSSLFILE = ../../tools/sdk/ssl/bearssl/build32/libbearssl.a ifeq (,$(wildcard $(LIBSSLFILE))) LIBSSL = else LIBSSL = $(LIBSSLFILE) endif ssl: # download source and build BearSSL - cd ../../tools/sdk/ssl && make native + cd ../../tools/sdk/ssl && make native32 CPP_OBJECTS_CORE_EMU = $(CPP_SOURCES_CORE_EMU:.cpp=.cpp.o) $(USERLIB:.cpp=.cpp.o) diff --git a/tests/host/README.txt b/tests/host/README.txt index 633750c56e..6b112652e9 100644 --- a/tests/host/README.txt +++ b/tests/host/README.txt @@ -42,7 +42,7 @@ Non exhaustive list of working examples: 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_CertStore/BearSSL_CertStore Compile other sketches: - library paths are specified using ULIBDIRS variable, separated by ':' diff --git a/tests/host/common/ArduinoMain.cpp b/tests/host/common/ArduinoMain.cpp index 320b160077..f161664fe8 100644 --- a/tests/host/common/ArduinoMain.cpp +++ b/tests/host/common/ArduinoMain.cpp @@ -66,22 +66,26 @@ void help (const char* argv0, int exitcode) " -h\n" " -i - use this interface for IP address\n" " -l - bind tcp/udp servers to interface only (not 0.0.0.0)\n" - ,argv0); + " -f - no throttle (possibly 100%%CPU)\n" + , argv0); exit(exitcode); } static struct option options[] = { { "help", no_argument, NULL, 'h' }, - { "local", required_argument, NULL, 'l' }, + { "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, "hli:", options, NULL); + int n = getopt_long(argc, argv, "hlfi:", options, NULL); if (n < 0) break; switch (n) @@ -95,6 +99,9 @@ int main (int argc, char* const argv []) 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); @@ -107,7 +114,8 @@ int main (int argc, char* const argv []) setup(); while (true) { - usleep(10000); // not 100% cpu + if (!fast) + usleep(10000); // not 100% cpu loop(); diff --git a/tests/host/common/MockTools.cpp b/tests/host/common/MockTools.cpp index 109a2418b8..7a89699de2 100644 --- a/tests/host/common/MockTools.cpp +++ b/tests/host/common/MockTools.cpp @@ -62,4 +62,18 @@ extern "C" void configTime(long timezone, int daylightOffset_sec, fprintf(stderr, MOCK "configTime: TODO (tz=%dH offset=%dS) (time will be host's)\n", (int)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) + }; diff --git a/tools/sdk/ssl/Makefile b/tools/sdk/ssl/Makefile index 4be4efa974..c84d0451cf 100644 --- a/tools/sdk/ssl/Makefile +++ b/tools/sdk/ssl/Makefile @@ -23,3 +23,6 @@ version-header: native: bearssl/README.txt cd bearssl && make + +native32: bearssl/README.txt + cd bearssl && make CONF=Unix32 From e597a252751b1fdfef90989d39c6fd9d7662f608 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Fri, 16 Nov 2018 01:31:42 +0100 Subject: [PATCH 29/50] fix make clean --- libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp | 2 +- tests/host/Makefile | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp index ab21d9509b..65b2555d04 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp @@ -40,7 +40,7 @@ extern "C" { #include "lwip/tcp.h" #include "lwip/inet.h" #include "lwip/netif.h" -#include "include/ClientContext.h" +#include #include "c_types.h" #include "coredecls.h" diff --git a/tests/host/Makefile b/tests/host/Makefile index 60da21b6ce..76acc87bdb 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -117,7 +117,7 @@ clean: clean-objects clean-coverage # clean everything rm -rf $(BINDIR) clean-objects: - rm -rf $(OBJECTS) $(CPP_OBJECTS_CORE_EMU) + rm -rf $(C_OBJECTS) $(CPP_OBJECTS_CORE) $(CPP_OBJECTS_CORE_EMU) clean-coverage: rm -rf $(COVERAGE_FILES) $(LCOV_DIRECTORY) *.gcov @@ -152,11 +152,11 @@ build-info: # show toolchain version $(CXX) $(PREINCLUDES) $(CXXFLAGS) $(INC_PATHS) -MD -MF $(BINDIR)/.$(notdir $<).d -c -o $@ $< $(BINDIR)/core.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE) - ar -rcu $@ $(C_OBJECTS) $(CPP_OBJECTS_CORE) + ar -rcu $@ $^ ranlib -c $@ $(OUTPUT_BINARY): $(CPP_OBJECTS_TESTS) $(BINDIR)/core.a - $(CXX) $(LDFLAGS) $(CPP_OBJECTS_TESTS) $(BINDIR)/core.a $(LIBS) -o $@ + $(CXX) $(LDFLAGS) $^ -o $@ ################################################# # building ino sources @@ -237,7 +237,7 @@ bin/fullcore.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE_EMU) $(CXX) $(LDFLAGS) $< bin/fullcore.a $(LIBSSL) -o $@ test -r $@ && ln -sf ../$@ $(BINDIR) || ln -sf $@ $(BINDIR) -.PRECIOUS: %.ino.cpp +#.PRECIOUS: %.ino.cpp %.ino.cpp: %.ino @s=$<; \ n=$${s##*/}; \ From bf42c2d025aee92d063fe610d86c7c280053a9ff Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Fri, 16 Nov 2018 01:58:14 +0100 Subject: [PATCH 30/50] make -m32 optional --- tests/host/Makefile | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/tests/host/Makefile b/tests/host/Makefile index 76acc87bdb..77bb623b4b 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -2,6 +2,12 @@ BINDIR := bin LCOV_DIRECTORY := lcov OUTPUT_BINARY := $(BINDIR)/host_tests CORE_PATH := ../../cores/esp8266 +ARCH32 = 1 + +ifeq ($(ARCH32),1) +N32 = 32 +M32 = -m32 +endif # I wasn't able to build with clang when -coverage flag is enabled, forcing GCC on OS X ifeq ($(shell uname -s),Darwin) @@ -84,9 +90,9 @@ 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 -O0 -fno-common -g -m32 -CFLAGS += -std=c99 -Wall -Werror -coverage -O0 -fno-common -g -m32 -LDFLAGS += -coverage -O0 -g -m32 +CXXFLAGS += $(DEBUG) -std=c++11 -Wall -Werror -coverage -O0 -fno-common -g $(M32) +CFLAGS += -std=c99 -Wall -Werror -coverage -O0 -fno-common -g $(M32) +LDFLAGS += -coverage -O0 -g $(M32) VALGRINDFLAGS += --leak-check=full --track-origins=yes --error-limit=no --show-leak-kinds=all --error-exitcode=999 # CXXFLAGS += -Wno-nonnull-compare # libraries/ESP8266WiFi/src/include/UdpContext.h:85:9: error: nonnull argument ‘this’ compared to NULL [-Werror=nonnull-compare] -- (if(this != 0)) @@ -217,14 +223,14 @@ 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 "WARNING: '$$dd' is not a directory" 1>&2; done; done) INC_PATHS += $(USERLIBDIRS) -LIBSSLFILE = ../../tools/sdk/ssl/bearssl/build32/libbearssl.a +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 native32 + cd ../../tools/sdk/ssl && make native$(N32) CPP_OBJECTS_CORE_EMU = $(CPP_SOURCES_CORE_EMU:.cpp=.cpp.o) $(USERLIB:.cpp=.cpp.o) From 1cc8f413a848443ace8a1de453a967775f1319c9 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Fri, 16 Nov 2018 11:12:52 +0100 Subject: [PATCH 31/50] 32bits compiler ability tester --- tests/host/Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/host/Makefile b/tests/host/Makefile index 77bb623b4b..3edf847f16 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -2,12 +2,17 @@ BINDIR := bin LCOV_DIRECTORY := lcov OUTPUT_BINARY := $(BINDIR)/host_tests CORE_PATH := ../../cores/esp8266 -ARCH32 = 1 +ARCH32 ?= 1 ifeq ($(ARCH32),1) +ABILITY32 = $(shell echo 'int main(){return sizeof(long);}'|cc -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 # I wasn't able to build with clang when -coverage flag is enabled, forcing GCC on OS X ifeq ($(shell uname -s),Darwin) From f9cd3c4adf7b3d51ec87a4d7c42a5161de4bc003 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Fri, 16 Nov 2018 11:34:49 +0100 Subject: [PATCH 32/50] WIP --- libraries/ESP8266WiFi/src/WiFiServer.cpp | 2 +- .../src/WiFiServerSecureBearSSL.cpp | 2 +- .../ESP8266WiFi/src/include/SSLContext.h | 2 +- tests/host/Makefile | 29 +++++++++++-------- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/libraries/ESP8266WiFi/src/WiFiServer.cpp b/libraries/ESP8266WiFi/src/WiFiServer.cpp index d1178d52d9..9e63da5054 100644 --- a/libraries/ESP8266WiFi/src/WiFiServer.cpp +++ b/libraries/ESP8266WiFi/src/WiFiServer.cpp @@ -35,7 +35,7 @@ extern "C" { #include "lwip/opt.h" #include "lwip/tcp.h" #include "lwip/inet.h" -#include "include/ClientContext.h" +#include WiFiServer::WiFiServer(IPAddress addr, uint16_t port) : _port(port) diff --git a/libraries/ESP8266WiFi/src/WiFiServerSecureBearSSL.cpp b/libraries/ESP8266WiFi/src/WiFiServerSecureBearSSL.cpp index 31d7536bb3..bea13dda01 100644 --- a/libraries/ESP8266WiFi/src/WiFiServerSecureBearSSL.cpp +++ b/libraries/ESP8266WiFi/src/WiFiServerSecureBearSSL.cpp @@ -34,7 +34,7 @@ extern "C" { #include "lwip/opt.h" #include "lwip/tcp.h" #include "lwip/inet.h" -#include "include/ClientContext.h" +#include #include "WiFiServerSecureBearSSL.h" namespace BearSSL { diff --git a/libraries/ESP8266WiFi/src/include/SSLContext.h b/libraries/ESP8266WiFi/src/include/SSLContext.h index 4e8cfe11f0..006fcd8743 100644 --- a/libraries/ESP8266WiFi/src/include/SSLContext.h +++ b/libraries/ESP8266WiFi/src/include/SSLContext.h @@ -37,7 +37,7 @@ extern "C" #include "lwip/tcp.h" #include "lwip/inet.h" #include "lwip/netif.h" -#include "include/ClientContext.h" +#include #include "c_types.h" namespace axTLS { diff --git a/tests/host/Makefile b/tests/host/Makefile index 3edf847f16..f1a39709b6 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -4,8 +4,18 @@ OUTPUT_BINARY := $(BINDIR)/host_tests CORE_PATH := ../../cores/esp8266 ARCH32 ?= 1 +# I wasn't able to build with clang when -coverage flag is enabled, forcing GCC on OS X +ifeq ($(shell uname -s),Darwin) +CC ?= gcc +CXX ?= g++ +endif +GCOV ?= gcov +VALGRIND ?= valgrind +LCOV ?= lcov +GENHTML ?= genhtml + ifeq ($(ARCH32),1) -ABILITY32 = $(shell echo 'int main(){return sizeof(long);}'|cc -m32 -x c - -o sizeoflong 2>/dev/null && ./sizeoflong; echo $$?; rm -f sizeoflong;) +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 @@ -14,15 +24,11 @@ M32 = -m32 endif endif -# I wasn't able to build with clang when -coverage flag is enabled, forcing GCC on OS X -ifeq ($(shell uname -s),Darwin) -CC ?= gcc -CXX ?= g++ +ifeq ($(N32),32) +$(warning compiling in 32 bits mode) +else +$(warning compiling in native mode) endif -GCOV ?= gcov -VALGRIND ?= valgrind -LCOV ?= lcov -GENHTML ?= genhtml $(shell mkdir -p $(BINDIR)) @@ -99,9 +105,8 @@ CXXFLAGS += $(DEBUG) -std=c++11 -Wall -Werror -coverage -O0 -fno-common -g $(M32 CFLAGS += -std=c99 -Wall -Werror -coverage -O0 -fno-common -g $(M32) LDFLAGS += -coverage -O0 -g $(M32) VALGRINDFLAGS += --leak-check=full --track-origins=yes --error-limit=no --show-leak-kinds=all --error-exitcode=999 -# -CXXFLAGS += -Wno-nonnull-compare # libraries/ESP8266WiFi/src/include/UdpContext.h:85:9: error: nonnull argument ‘this’ compared to NULL [-Werror=nonnull-compare] -- (if(this != 0)) -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-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)))) From 4c4288b36d10af160d4d70d6ba3c2101d6b177fa Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Fri, 16 Nov 2018 11:44:10 +0100 Subject: [PATCH 33/50] WIP (fix 1 vtable error, still another one to hunt with using spiffs) --- cores/esp8266/FSImpl.h | 1 + 1 file changed, 1 insertion(+) diff --git a/cores/esp8266/FSImpl.h b/cores/esp8266/FSImpl.h index e5694b5f68..cf84be6a6e 100644 --- a/cores/esp8266/FSImpl.h +++ b/cores/esp8266/FSImpl.h @@ -62,6 +62,7 @@ class DirImpl { class FSImpl { public: + virtual ~FSImpl () { } virtual bool begin() = 0; virtual void end() = 0; virtual bool format() = 0; From 77b61d1d1fc1571714473719ea3746f1ba1abd9a Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Fri, 16 Nov 2018 11:50:21 +0100 Subject: [PATCH 34/50] example astyle --- libraries/ESP8266WiFi/examples/udp/udp.ino | 43 ++-------------------- 1 file changed, 3 insertions(+), 40 deletions(-) diff --git a/libraries/ESP8266WiFi/examples/udp/udp.ino b/libraries/ESP8266WiFi/examples/udp/udp.ino index fb3cb7d911..a43a8ea78a 100644 --- a/libraries/ESP8266WiFi/examples/udp/udp.ino +++ b/libraries/ESP8266WiFi/examples/udp/udp.ino @@ -73,45 +73,8 @@ void loop() { delay(10); } - /* - Processing sketch to run with this example - ===================================================== - - // Processing UDP example to send and receive string data from Arduino - // press any key to send the "Hello Arduino" message - - - import hypermedia.net.*; - - UDP udp; // define the UDP object - - - void setup() { - udp = new UDP( this, 6000 ); // create a new datagram connection on port 6000 - //udp.log( true ); // <-- printout the connection activity - udp.listen( true ); // and wait for incoming message - } - - void draw() - { - } - - void keyPressed() { - String ip = "192.168.1.177"; // the remote IP address - int port = 8888; // the destination port - - udp.send("Hello World", ip, port ); // the message to send - - } - - void receive( byte[] data ) { // <-- default handler - //void receive( byte[] data, String ip, int port ) { // <-- extended handler - - for(int i=0; i < data.length; i++) - print(char(data[i])); - println(); - } + test (shell/netcat): + --------------- + nc -u 192.168.esp.address 8888 */ - - From 6565a99a722297d89ed32027550f29cc50876f89 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Fri, 16 Nov 2018 12:00:03 +0100 Subject: [PATCH 35/50] fix os_printf_plus --- tests/host/common/mock.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/host/common/mock.h b/tests/host/common/mock.h index 75aff27c61..5ef1d89924 100644 --- a/tests/host/common/mock.h +++ b/tests/host/common/mock.h @@ -63,7 +63,7 @@ typedef uint32_t uint32; extern "C" { #endif int ets_printf (const char* fmt, ...) __attribute__ ((format (printf, 1, 2))); -#define os_printf_plus ets_printf +#define os_printf_plus printf extern const char* host_interface; // cmdline parameter From 706b313cbf11e3aef3ae2275e4d5ad58aeca975b Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Fri, 16 Nov 2018 16:43:24 +0100 Subject: [PATCH 36/50] load / save mock spiffs --- tests/host/common/spiffs_mock.cpp | 70 +++++++++++++++++++++++++++++-- tests/host/common/spiffs_mock.h | 21 ++++++++-- tests/host/fs/test_fs.cpp | 22 +++++----- 3 files changed, 96 insertions(+), 17 deletions(-) diff --git a/tests/host/common/spiffs_mock.cpp b/tests/host/common/spiffs_mock.cpp index 46ea855c4c..fb8c47692d 100644 --- a/tests/host/common/spiffs_mock.cpp +++ b/tests/host/common/spiffs_mock.cpp @@ -22,6 +22,13 @@ #include +#include +#include +#include +#include + +#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: %d bytes\n", (int)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(fs_size); s_phys_page = static_cast(fs_page); s_phys_block = static_cast(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 %i bytes from '%s'\n", (int)m_fs_size, fname); + if (::read(fs, &m_fs[0], m_fs_size) != (ssize_t)m_fs_size) + fprintf(stderr, "SPIFFS: reading %i bytes: %s\n", (int)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 %i bytes to '%s'\n", (int)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%d:%d ",(int)i, (int)m_fs[i]); + + if (::write(fs, &m_fs[0], m_fs_size) != (ssize_t)m_fs_size) + fprintf(stderr, "SPIFFS: writing %i bytes: %s\n", (int)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; diff --git a/tests/host/common/spiffs_mock.h b/tests/host/common/spiffs_mock.h index d54bc6df23..6b0c2c5102 100644 --- a/tests/host/common/spiffs_mock.h +++ b/tests/host/common/spiffs_mock.h @@ -21,17 +21,32 @@ #include #include +#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 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() diff --git a/tests/host/fs/test_fs.cpp b/tests/host/fs/test_fs.cpp index 6e14af84f2..c97e0f718b 100644 --- a/tests/host/fs/test_fs.cpp +++ b/tests/host/fs/test_fs.cpp @@ -50,25 +50,25 @@ static std::set listDir (const char* path) TEST_CASE("FS can begin","[fs]") { - SPIFFS_MOCK_DECLARE(64, 8, 512); + 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"); From 747f3b3448a1d5c63fbd48dfd1611575a0321e22 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Fri, 16 Nov 2018 16:44:01 +0100 Subject: [PATCH 37/50] fix style --- libraries/ESP8266WiFi/examples/udp/udp.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266WiFi/examples/udp/udp.ino b/libraries/ESP8266WiFi/examples/udp/udp.ino index a43a8ea78a..5759905bd2 100644 --- a/libraries/ESP8266WiFi/examples/udp/udp.ino +++ b/libraries/ESP8266WiFi/examples/udp/udp.ino @@ -10,7 +10,7 @@ by Michael Margolis This code is in the public domain. - + adapted from Ethernet library examples */ From 940c0f1f0282c06e7ff2dddee31cf64fb4f2d42c Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Fri, 16 Nov 2018 16:44:33 +0100 Subject: [PATCH 38/50] fix using spiffs/mock --- cores/esp8266/spiffs_api.cpp | 4 +++- tests/common.sh | 2 +- tests/host/Makefile | 12 ++++++------ tests/host/common/ArduinoMain.cpp | 6 ++++++ tests/host/common/WMath.cpp | 1 + 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/cores/esp8266/spiffs_api.cpp b/cores/esp8266/spiffs_api.cpp index 390a6412fd..a8e522f038 100644 --- a/cores/esp8266/spiffs_api.cpp +++ b/cores/esp8266/spiffs_api.cpp @@ -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 diff --git a/tests/common.sh b/tests/common.sh index 8deb65d5a1..e219c7353c 100755 --- a/tests/common.sh +++ b/tests/common.sh @@ -134,7 +134,7 @@ function build_docs() function run_host_tests() { pushd host - make CI + make ARCH32=0 CI make clean-objects popd } diff --git a/tests/host/Makefile b/tests/host/Makefile index f1a39709b6..fb01561bc4 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -38,10 +38,10 @@ CORE_CPP_FILES := $(addprefix $(CORE_PATH)/,\ WString.cpp \ Print.cpp \ FS.cpp \ + spiffs_api.cpp \ pgmspace.cpp \ MD5Builder.cpp \ ) -# spiffs_api.cpp \ CORE_C_FILES := $(addprefix $(CORE_PATH)/,\ core_esp8266_noniso.c \ @@ -58,6 +58,7 @@ MOCK_CPP_FILES_COMMON := $(addprefix common/,\ spiffs_mock.cpp \ WMath.cpp \ HardwareSerial.cpp \ + MockTools.cpp \ ) MOCK_CPP_FILES := $(MOCK_CPP_FILES_COMMON) $(addprefix common/,\ @@ -77,12 +78,12 @@ MOCK_C_FILES := $(addprefix common/,\ INC_PATHS := $(addprefix -I,\ common \ $(CORE_PATH) \ - $(shell echo ../../libraries/*/src) \ - $(shell echo ../../libraries/*) \ - ../../tools/sdk/include \ ) INC_PATHS += $(addprefix -I,\ + $(shell echo ../../libraries/*/src) \ + $(shell echo ../../libraries/*) \ + ../../tools/sdk/include \ ../../tools/sdk/lwip2/include \ ) @@ -133,7 +134,7 @@ clean: clean-objects clean-coverage # clean everything rm -rf $(BINDIR) clean-objects: - rm -rf $(C_OBJECTS) $(CPP_OBJECTS_CORE) $(CPP_OBJECTS_CORE_EMU) + rm -rf $(C_OBJECTS) $(CPP_OBJECTS_CORE) $(CPP_OBJECTS_CORE_EMU) $(CPP_OBJECTS_TESTS) clean-coverage: rm -rf $(COVERAGE_FILES) $(LCOV_DIRECTORY) *.gcov @@ -217,7 +218,6 @@ MOCK_ARDUINO_LIBS := \ common/MockWiFiServer.cpp \ common/MockUDPSocket.cpp \ common/ArduinoWire.cpp \ - common/MockTools.cpp \ common/MockEsp.cpp \ common/MockEEPROM.cpp \ common/MockSPI.cpp \ diff --git a/tests/host/common/ArduinoMain.cpp b/tests/host/common/ArduinoMain.cpp index f161664fe8..359e7985e5 100644 --- a/tests/host/common/ArduinoMain.cpp +++ b/tests/host/common/ArduinoMain.cpp @@ -46,6 +46,12 @@ #include +#if 0 +#include "../common/spiffs_mock.h" +#include +SPIFFS_MOCK_DECLARE(/*size_kb*/1024, /(blovk_kb*/8, /*page_b*/512); +#endif + std::map udps; void register_udp (int sock, UdpContext* udp) diff --git a/tests/host/common/WMath.cpp b/tests/host/common/WMath.cpp index 4201b20ead..4fdf07fa2e 100644 --- a/tests/host/common/WMath.cpp +++ b/tests/host/common/WMath.cpp @@ -25,6 +25,7 @@ extern "C" { #include +#include } void randomSeed(unsigned long seed) { From 3510f9349efc06f7b1eb4582d770448f76392307 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Fri, 16 Nov 2018 23:16:01 +0100 Subject: [PATCH 39/50] don't mess ram --- .../ESP8266WebServer/src/ESP8266WebServer.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp index 1435a463ae..8f2404994a 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp @@ -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", (unsigned)len, footer); - _currentClientWrite(chunkSize, strlen(chunkSize)); - free(chunkSize); - } + char chunkSize[11]; + sprintf(chunkSize, "%x\r\n", (unsigned)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", (unsigned)size, footer); - _currentClientWrite(chunkSize, strlen(chunkSize)); - free(chunkSize); - } + char chunkSize[11]; + sprintf(chunkSize, "%x\r\n", (unsigned)size); + _currentClientWrite(chunkSize, strlen(chunkSize)); } _currentClientWrite_P(content, size); if(_chunked){ From 81d471f5ea8f14ea9c2fca91d1995cd409e34e71 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Fri, 16 Nov 2018 23:16:20 +0100 Subject: [PATCH 40/50] update doc --- tests/host/README.txt | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/tests/host/README.txt b/tests/host/README.txt index 6b112652e9..f2ca8028b5 100644 --- a/tests/host/README.txt +++ b/tests/host/README.txt @@ -5,8 +5,8 @@ Host Tests for Continuous Integration make CI -Host emulation (WIP) --------------------- +Sketch emulation on host +------------------------ This environment let compile esp8266/Arduino sketches into native environment. Network (tcp, udp, including ssl and multicast) is linked to @@ -42,7 +42,7 @@ Non exhaustive list of working examples: 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_CertStore/BearSSL_CertStore + make D=1 ../../libraries/ESP8266WiFi/examples/BearSSL_Validation/BearSSL_Validation Compile other sketches: - library paths are specified using ULIBDIRS variable, separated by ':' @@ -64,18 +64,6 @@ Build all examples with debug enabled (D=1): (not fully working yet) Running a sketch ---------------- -- SPIFFS - (already done, to check) - -- SDCARD - (TODO) - -- EEPROM - (to check) a file named 'eeprom' is created in current directory for reading and writing. - -- Serial: - for now Serial.read() returns -1. Serial.write() will printf(). - - GPIOs read as 0(digital) or 512(analog). output is printed on console. @@ -87,8 +75,19 @@ 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. + +- spiffs in a file (done, need to initialize and check) +- EEPROM in a file (partly done) +- SDCARD on Host filesystem ? +- 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 +- compile and use lwIP on host +#1715 From 7bf8ab2c53aa4aff5d04d3b4705390f050691c17 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Fri, 16 Nov 2018 23:16:35 +0100 Subject: [PATCH 41/50] remove leftover --- tests/host/common/MockEEPROM.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/host/common/MockEEPROM.cpp b/tests/host/common/MockEEPROM.cpp index 0f882ca0bd..6357c73dd2 100644 --- a/tests/host/common/MockEEPROM.cpp +++ b/tests/host/common/MockEEPROM.cpp @@ -90,13 +90,6 @@ void EEPROMClass::write (int x, uint8_t c) fprintf(stderr, MOCK "eeprom: %s\n\r", strerror(errno)); } -#if 0 -void EEPROMClass::update (int x, char c) -{ - put(x, c); -} -#endif - #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_EEPROM) EEPROMClass EEPROM; #endif From a04996ce272163730f45599050541058f3f4bc65 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Fri, 16 Nov 2018 23:53:41 +0100 Subject: [PATCH 42/50] optimization -Os except for CI, rename ARCH32 to FORCE32 --- tests/common.sh | 2 +- tests/host/Makefile | 12 +++++++----- tests/host/README.txt | 3 ++- tests/host/common/include/UdpContext.h | 8 +++++++- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/tests/common.sh b/tests/common.sh index e219c7353c..dbbb070e1a 100755 --- a/tests/common.sh +++ b/tests/common.sh @@ -134,7 +134,7 @@ function build_docs() function run_host_tests() { pushd host - make ARCH32=0 CI + make FORCE32=0 OPTZ=-O0 CI make clean-objects popd } diff --git a/tests/host/Makefile b/tests/host/Makefile index fb01561bc4..83b60ab70c 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -2,7 +2,8 @@ BINDIR := bin LCOV_DIRECTORY := lcov OUTPUT_BINARY := $(BINDIR)/host_tests CORE_PATH := ../../cores/esp8266 -ARCH32 ?= 1 +FORCE32 ?= 1 +OPTZ ?= -Os # I wasn't able to build with clang when -coverage flag is enabled, forcing GCC on OS X ifeq ($(shell uname -s),Darwin) @@ -14,7 +15,7 @@ VALGRIND ?= valgrind LCOV ?= lcov GENHTML ?= genhtml -ifeq ($(ARCH32),1) +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) @@ -98,13 +99,14 @@ PREINCLUDES := \ -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 -O0 -fno-common -g $(M32) -CFLAGS += -std=c99 -Wall -Werror -coverage -O0 -fno-common -g $(M32) -LDFLAGS += -coverage -O0 -g $(M32) +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)) diff --git a/tests/host/README.txt b/tests/host/README.txt index f2ca8028b5..c7c13ceb67 100644 --- a/tests/host/README.txt +++ b/tests/host/README.txt @@ -2,8 +2,9 @@ Host Tests for Continuous Integration ------------------------------------- - make CI + make FORCE32=0 OPTZ=-O0 CI + (FORCE32=0: https://bugs.launchpad.net/ubuntu/+source/valgrind/+bug/948004) Sketch emulation on host ------------------------ diff --git a/tests/host/common/include/UdpContext.h b/tests/host/common/include/UdpContext.h index 7e9c279952..30177f0e71 100644 --- a/tests/host/common/include/UdpContext.h +++ b/tests/host/common/include/UdpContext.h @@ -215,7 +215,13 @@ class UdpContext void translate_addr () { if (addrsize == 4) - ip4_addr_set_u32(&ip_2_ip4(_dst), *(uint32_t*)addr); // XXX should use lwip_ntohl? + { + 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); } From ffe9811b641aa5df3bda8e9ed855234f5c2c9643 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Sun, 18 Nov 2018 23:08:24 +0100 Subject: [PATCH 43/50] revert useless cast (not even compiled) --- cores/esp8266/Esp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index 97a7955cd2..2bbe2f933b 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -481,7 +481,7 @@ uint32_t EspClass::getFreeSketchSpace() { uint32_t usedSize = getSketchSize(); // round one sector up uint32_t freeSpaceStart = (usedSize + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1)); - uint32_t freeSpaceEnd = (uint32_t)(unsigned long)&_SPIFFS_start - 0x40200000; + uint32_t freeSpaceEnd = (uint32_t)&_SPIFFS_start - 0x40200000; #ifdef DEBUG_SERIAL DEBUG_SERIAL.printf("usedSize=%u freeSpaceStart=%u freeSpaceEnd=%u\r\n", usedSize, freeSpaceStart, freeSpaceEnd); From 148bb78be238b01016e61e90d4286194408b0682 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Sun, 18 Nov 2018 23:08:51 +0100 Subject: [PATCH 44/50] remove unused function --- tests/host/common/MockUDPSocket.cpp | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/tests/host/common/MockUDPSocket.cpp b/tests/host/common/MockUDPSocket.cpp index 017b0cb769..fa20f7bd80 100644 --- a/tests/host/common/MockUDPSocket.cpp +++ b/tests/host/common/MockUDPSocket.cpp @@ -104,23 +104,6 @@ bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast) } -size_t mockUDPFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize, void* addrbuf, uint32_t* addrbufsize) -{ - socklen_t realaddrbufsize = addrbufsize? *addrbufsize: 0; - - size_t maxread = CCBUFSIZE - ccinbufsize; - ssize_t ret = ::recvfrom(sock, ccinbuf + ccinbufsize, maxread, 0/*flags*/, (sockaddr*)addrbuf, &realaddrbufsize); - *addrbufsize = realaddrbufsize; - if (ret == -1) - { - if (errno != EAGAIN) - fprintf(stderr, MOCK "UDPContext::(read/peek): filling buffer for %d bytes: %s\n", (int)maxread, strerror(errno)); - ret = 0; - } - - return ccinbufsize += ret; -} - size_t mockUDPFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize, uint8_t& addrsize, uint8_t addr[16], uint16_t& port) { struct sockaddr_storage addrbuf; From 8bf7b015cc89284b39828aaf80f19e5eb66c43d4 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Sun, 18 Nov 2018 23:38:01 +0100 Subject: [PATCH 45/50] use proper type for pointer arithmetics --- cores/esp8266/Updater.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cores/esp8266/Updater.cpp b/cores/esp8266/Updater.cpp index 8c0dce66a0..a9159f1f28 100644 --- a/cores/esp8266/Updater.cpp +++ b/cores/esp8266/Updater.cpp @@ -84,12 +84,12 @@ 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)); //address of the end of the space available for sketch and update - uint32_t updateEndAddress = (uint32_t)(unsigned long)&_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)); //address where we will start writing the update @@ -97,7 +97,7 @@ bool UpdaterClass::begin(size_t size, int command, int ledPin, uint8_t ledOn) { #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] updateEndAddress: 0x%08X (%d)\n", (int)updateEndAddress, (int)updateEndAddress); DEBUG_UPDATER.printf("[begin] currentSketchSize: 0x%08X (%d)\n", currentSketchSize, currentSketchSize); #endif @@ -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)(unsigned long)&_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", (unsigned)_size, (unsigned)_size); + DEBUG_UPDATER.printf("[begin] _size: 0x%08X (%d)\n", (int)_size, (int)_size); #endif _md5.begin(); From c7bc1460bf3030b1bc1beb3b2c203038965b7a86 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Mon, 19 Nov 2018 23:03:49 +0100 Subject: [PATCH 46/50] makefile: sketch object and cpp file moved to bin/ directories easier to clean, and IDE don't like them --- tests/host/Makefile | 85 ++++++++++++++++++++++++------------------- tests/host/README.txt | 8 ++-- 2 files changed, 52 insertions(+), 41 deletions(-) diff --git a/tests/host/Makefile b/tests/host/Makefile index 83b60ab70c..e90831d624 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -5,6 +5,8 @@ CORE_PATH := ../../cores/esp8266 FORCE32 ?= 1 OPTZ ?= -Os +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) CC ?= gcc @@ -167,6 +169,7 @@ build-info: # show toolchain version %.c.o: %.c $(CC) $(PREINCLUDES) $(CFLAGS) $(INC_PATHS) -MD -MF $(BINDIR)/.$(notdir $<).d -c -o $@ $< +.PRECIOUS: %.cpp.o %.cpp.o: %.cpp $(CXX) $(PREINCLUDES) $(CXXFLAGS) $(INC_PATHS) -MD -MF $(BINDIR)/.$(notdir $<).d -c -o $@ $< @@ -231,10 +234,6 @@ CPP_SOURCES_CORE_EMU = \ $(ARDUINO_LIBS) \ -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 "WARNING: '$$dd' is not a directory" 1>&2; done; done) -INC_PATHS += $(USERLIBDIRS) - LIBSSLFILE = ../../tools/sdk/ssl/bearssl/build$(N32)/libbearssl.a ifeq (,$(wildcard $(LIBSSLFILE))) LIBSSL = @@ -244,31 +243,60 @@ endif ssl: # download source and build BearSSL cd ../../tools/sdk/ssl && make native$(N32) -CPP_OBJECTS_CORE_EMU = $(CPP_SOURCES_CORE_EMU:.cpp=.cpp.o) $(USERLIB:.cpp=.cpp.o) +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) ar -rcu $@ $^ ranlib -c $@ -.PRECIOUS: %.cpp.o %: %.ino.cpp.o bin/fullcore.a $(CXX) $(LDFLAGS) $< bin/fullcore.a $(LIBSSL) -o $@ - test -r $@ && ln -sf ../$@ $(BINDIR) || ln -sf $@ $(BINDIR) - -#.PRECIOUS: %.ino.cpp -%.ino.cpp: %.ino - @s=$<; \ - n=$${s##*/}; \ - (cd $${s%/*}; \ - echo "#include \"$$n\""; \ - for i in *.ino; do \ - test "$$i" = "$$n" || echo "#include \"$$i\""; \ - done; \ - ) > $@ + @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 +##################### + +################################################# +# (debug) + +# https://lists.gnu.org/archive/html/help-make/2002-11/msg00062.html +# Bad gmake, never *ever* try to get a file out of source control by yourself. +#%: %,v +#%: RCS/%,v +#%: RCS/% +#%: s.% +#%: SCCS/s.% + +#Makefile: ; ################################################# -# Makefile.inc.ino generation --include $(BINDIR)/Makefile.inc.ino .PHONY: list list: # show core example list @@ -281,26 +309,9 @@ list: # show core example list done; \ done; \ -$(BINDIR)/Makefile.inc.ino: - @all=""; \ - for dir in ../../libraries/*/examples; do \ - exampledir=$${dir%/*}; \ - exampledirname=$${exampledir##*/}; \ - for subdir in $$dir/*; do \ - exname=$${subdir##*/}; \ - all="$$all $$subdir/$$exname"; \ - done; \ - done; \ - echo "examples: $$all" > $@ - -examples: $(BINDIR)/Makefile.inc.ino # build all core examples - $(MAKE) $@ - ################################################# # help -MAKEFILE = $(word 1, $(MAKEFILE_LIST)) - .PHONY: help help: @cat README.txt diff --git a/tests/host/README.txt b/tests/host/README.txt index c7c13ceb67..c0b500ebe0 100644 --- a/tests/host/README.txt +++ b/tests/host/README.txt @@ -22,7 +22,7 @@ instead. How to compile a sketch ----------------------- -All results are stored or linked from ./bin/ . +All results are stored in ./bin/ . Show the core example list: make list @@ -50,11 +50,11 @@ Compile other sketches: - 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:/path/to/another/one /path/to/your/sketchdir/sketch/sketch + 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:/path/to/another/one make D=1 /path/to/your/sketchdir/sketch/sketch + ULIBDIRS=/path/to/your/arduino/libraries/lib1:/path/to/another/place/lib2 make D=1 /path/to/your/sketchdir/sketch/sketch or - export ULIBDIRS=/path/to/your/arduino/libraries:/path/to/another/one + export ULIBDIRS=/path/to/your/arduino/libraries/lib1:/path/to/another/place/lib2 make D=1 /path/to/your/sketchdir/sketch/sketch From 2f109c4060e7bd27ad48a537f541b920bb3129a6 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Tue, 20 Nov 2018 01:58:14 +0100 Subject: [PATCH 47/50] changes for review --- .../CaptivePortalAdvanced.ino | 11 -------- .../AdvancedWebServer/AdvancedWebServer.ino | 2 -- tests/host/Makefile | 8 +++--- tests/host/README.txt | 26 +++++++++++-------- tests/host/common/ArduinoMain.cpp | 2 +- ...textSocket.cpp => ClientContextSocket.cpp} | 0 ...ientContext.cpp => ClientContextTools.cpp} | 0 tests/host/common/MockWiFiServer.cpp | 6 +++-- tests/host/common/MockWiFiServerSocket.cpp | 6 +++-- .../common/{ArduinoWire.cpp => MockWire.cpp} | 0 ...MockUDPSocket.cpp => UdpContextSocket.cpp} | 0 11 files changed, 28 insertions(+), 33 deletions(-) rename tests/host/common/{MockClientContextSocket.cpp => ClientContextSocket.cpp} (100%) rename tests/host/common/{MockClientContext.cpp => ClientContextTools.cpp} (100%) rename tests/host/common/{ArduinoWire.cpp => MockWire.cpp} (100%) rename tests/host/common/{MockUDPSocket.cpp => UdpContextSocket.cpp} (100%) diff --git a/libraries/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino b/libraries/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino index 4ce62a5e60..8c662fd206 100644 --- a/libraries/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino +++ b/libraries/DNSServer/examples/CaptivePortalAdvanced/CaptivePortalAdvanced.ino @@ -5,17 +5,6 @@ #include #include -boolean isIp(String str); -String toStringIp(IPAddress ip); -void loadCredentials(); -void saveCredentials(); -void handleRoot(); -boolean captivePortal(); -void handleWifi(); -void handleWifiSave(); -void handleNotFound(); - - /* This example serves a "hello world" on a WLAN and a SoftAP at the same time. The SoftAP allow you to configure WLAN parameters at run time. They are not setup in the sketch but saved on EEPROM. diff --git a/libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino b/libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino index b19d120b32..1315c9a30c 100644 --- a/libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino +++ b/libraries/ESP8266WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino @@ -40,8 +40,6 @@ ESP8266WebServer server(80); const int led = 13; -void drawGraph(); - void handleRoot() { digitalWrite(led, 1); char temp[400]; diff --git a/tests/host/Makefile b/tests/host/Makefile index e90831d624..cd0f92fa5e 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -217,12 +217,12 @@ ARDUINO_LIBS := \ ) \ MOCK_ARDUINO_LIBS := \ - common/MockClientContextSocket.cpp \ - common/MockClientContext.cpp \ + common/ClientContextSocket.cpp \ + common/ClientContextTools.cpp \ common/MockWiFiServerSocket.cpp \ common/MockWiFiServer.cpp \ - common/MockUDPSocket.cpp \ - common/ArduinoWire.cpp \ + common/UdpContextSocket.cpp \ + common/MockWire.cpp \ common/MockEsp.cpp \ common/MockEEPROM.cpp \ common/MockSPI.cpp \ diff --git a/tests/host/README.txt b/tests/host/README.txt index c0b500ebe0..475278135b 100644 --- a/tests/host/README.txt +++ b/tests/host/README.txt @@ -34,7 +34,9 @@ run it: ./bin/Blink -h -Optional 'D=1' enables core debug. +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: @@ -51,15 +53,16 @@ Compile other sketches: - 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 + or: ULIBDIRS=/path/to/your/arduino/libraries/lib1:/path/to/another/place/lib2 make D=1 /path/to/your/sketchdir/sketch/sketch - or - export ULIBDIRS=/path/to/your/arduino/libraries/lib1:/path/to/another/place/lib2 - make D=1 /path/to/your/sketchdir/sketch/sketch - -Build all examples with debug enabled (D=1): (not fully working yet) - make D=1 examples + 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 Running a sketch @@ -85,10 +88,11 @@ Make fun, propose PRs. - spiffs in a file (done, need to initialize and check) - EEPROM in a file (partly done) -- SDCARD on Host filesystem ? +- 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 +- store sketch objects and binaries outside from the source directories (done for sketches) - compile and use lwIP on host -#1715 +- easily debug HTTP classes +- https://github.com/esp8266/Arduino/issues/1715 diff --git a/tests/host/common/ArduinoMain.cpp b/tests/host/common/ArduinoMain.cpp index 359e7985e5..e32999dd30 100644 --- a/tests/host/common/ArduinoMain.cpp +++ b/tests/host/common/ArduinoMain.cpp @@ -133,7 +133,7 @@ int main (int argc, char* const argv []) p.events = POLLIN; if (poll(&p, 1, 0) && p.revents == POLLIN) { - fprintf(stderr, MOCK "UDP poll(%d) -> cb\n", (int)p.fd); + fprintf(stderr, MOCK "UDP poll(%d) -> cb\r", (int)p.fd); udp.second->mock_cb(); } } diff --git a/tests/host/common/MockClientContextSocket.cpp b/tests/host/common/ClientContextSocket.cpp similarity index 100% rename from tests/host/common/MockClientContextSocket.cpp rename to tests/host/common/ClientContextSocket.cpp diff --git a/tests/host/common/MockClientContext.cpp b/tests/host/common/ClientContextTools.cpp similarity index 100% rename from tests/host/common/MockClientContext.cpp rename to tests/host/common/ClientContextTools.cpp diff --git a/tests/host/common/MockWiFiServer.cpp b/tests/host/common/MockWiFiServer.cpp index 0150e436ec..5a03f8d87d 100644 --- a/tests/host/common/MockWiFiServer.cpp +++ b/tests/host/common/MockWiFiServer.cpp @@ -39,8 +39,10 @@ extern "C" const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY); -#define int2pcb(x) ((tcp_pcb*)(long)(x)) -#define pcb2int(x) ((int)(long)(x)) +#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) { diff --git a/tests/host/common/MockWiFiServerSocket.cpp b/tests/host/common/MockWiFiServerSocket.cpp index 7c9a0333db..b866fdce3c 100644 --- a/tests/host/common/MockWiFiServerSocket.cpp +++ b/tests/host/common/MockWiFiServerSocket.cpp @@ -37,8 +37,10 @@ #include #include -#define int2pcb(x) ((tcp_pcb*)(long)(x)) -#define pcb2int(x) ((int)(long)(x)) +#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) { diff --git a/tests/host/common/ArduinoWire.cpp b/tests/host/common/MockWire.cpp similarity index 100% rename from tests/host/common/ArduinoWire.cpp rename to tests/host/common/MockWire.cpp diff --git a/tests/host/common/MockUDPSocket.cpp b/tests/host/common/UdpContextSocket.cpp similarity index 100% rename from tests/host/common/MockUDPSocket.cpp rename to tests/host/common/UdpContextSocket.cpp From 2d4c89b4de6bcf685d60c06fa68ea5415f743110 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Tue, 20 Nov 2018 13:31:52 +0100 Subject: [PATCH 48/50] make use of %zd --- cores/esp8266/Updater.cpp | 18 +++++------ cores/esp8266/spiffs_api.h | 6 ++-- .../src/ESP8266HTTPClient.cpp | 2 +- .../ESP8266WebServer/src/ESP8266WebServer.cpp | 4 +-- .../src/WiFiClientSecureBearSSL.cpp | 2 +- tests/host/Makefile | 4 +-- tests/host/common/ArduinoMain.cpp | 9 +++--- tests/host/common/ClientContextSocket.cpp | 6 ++-- .../common/{MockWire.cpp => HostWiring.cpp} | 0 .../{HardwareSerial.cpp => MockSerial.cpp} | 0 tests/host/common/MockTools.cpp | 4 +-- tests/host/common/MockWiFiServerSocket.cpp | 8 ++--- tests/host/common/UdpContextSocket.cpp | 30 +++++++++---------- tests/host/common/include/UdpContext.h | 10 +++---- tests/host/common/spiffs_mock.cpp | 18 +++++------ 15 files changed, 60 insertions(+), 61 deletions(-) rename tests/host/common/{MockWire.cpp => HostWiring.cpp} (100%) rename tests/host/common/{HardwareSerial.cpp => MockSerial.cpp} (100%) diff --git a/cores/esp8266/Updater.cpp b/cores/esp8266/Updater.cpp index a9159f1f28..c4fdb5a67f 100644 --- a/cores/esp8266/Updater.cpp +++ b/cores/esp8266/Updater.cpp @@ -87,18 +87,18 @@ bool UpdaterClass::begin(size_t size, int command, int ledPin, uint8_t ledOn) { 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 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", (int)updateEndAddress, (int)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) @@ -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", (int)_size, (int)_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(), (unsigned)progress(), (unsigned)_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, (unsigned)_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, (unsigned)_size); + DEBUG_UPDATER.printf("SPIFFS: address:0x%08X, size:0x%08zX\n", _startAddress, _size); #endif } diff --git a/cores/esp8266/spiffs_api.h b/cores/esp8266/spiffs_api.h index ef47f79be4..3a0cb032e1 100644 --- a/cores/esp8266/spiffs_api.h +++ b/cores/esp8266/spiffs_api.h @@ -220,9 +220,9 @@ class SPIFFSImpl : public FSImpl size_t cacheBufSize = SPIFFS_buffer_bytes_for_cache(&_fs, _maxOpenFds); if (!_workBuf) { - DEBUGV("SPIFFSImpl: allocating %d+%d+%d=%d bytes\r\n", - (int)workBufSize, (int)fdsBufSize, (int)cacheBufSize, - (int)(workBufSize + fdsBufSize + cacheBufSize)); + DEBUGV("SPIFFSImpl: allocating %zd+%zd+%zd=%zd bytes\r\n", + workBufSize, fdsBufSize, cacheBufSize, + workBufSize + fdsBufSize + cacheBufSize); _workBuf.reset(new uint8_t[workBufSize]); _fdsBuf.reset(new uint8_t[fdsBufSize]); _cacheBuf.reset(new uint8_t[cacheBufSize]); diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index d3369ddc69..a3fbdd9b24 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -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, (int)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 { diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp index 8f2404994a..6e8cc0a5de 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp @@ -439,7 +439,7 @@ void ESP8266WebServer::sendContent(const String& content) { size_t len = content.length(); if(_chunked) { char chunkSize[11]; - sprintf(chunkSize, "%x\r\n", (unsigned)len); + sprintf(chunkSize, "%zx\r\n", len); _currentClientWrite(chunkSize, strlen(chunkSize)); } _currentClientWrite(content.c_str(), len); @@ -459,7 +459,7 @@ void ESP8266WebServer::sendContent_P(PGM_P content, size_t size) { const char * footer = "\r\n"; if(_chunked) { char chunkSize[11]; - sprintf(chunkSize, "%x\r\n", (unsigned)size); + sprintf(chunkSize, "%zx\r\n", size); _currentClientWrite(chunkSize, strlen(chunkSize)); } _currentClientWrite_P(content, size); diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp index 65b2555d04..fe11be8f39 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp @@ -1405,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, (int)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"); } diff --git a/tests/host/Makefile b/tests/host/Makefile index cd0f92fa5e..8986009e41 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -60,7 +60,7 @@ MOCK_CPP_FILES_COMMON := $(addprefix common/,\ Arduino.cpp \ spiffs_mock.cpp \ WMath.cpp \ - HardwareSerial.cpp \ + MockSerial.cpp \ MockTools.cpp \ ) @@ -222,7 +222,7 @@ MOCK_ARDUINO_LIBS := \ common/MockWiFiServerSocket.cpp \ common/MockWiFiServer.cpp \ common/UdpContextSocket.cpp \ - common/MockWire.cpp \ + common/HostWiring.cpp \ common/MockEsp.cpp \ common/MockEEPROM.cpp \ common/MockSPI.cpp \ diff --git a/tests/host/common/ArduinoMain.cpp b/tests/host/common/ArduinoMain.cpp index e32999dd30..900b865aef 100644 --- a/tests/host/common/ArduinoMain.cpp +++ b/tests/host/common/ArduinoMain.cpp @@ -113,7 +113,7 @@ int main (int argc, char* const argv []) exit(EXIT_FAILURE); } } - + // setup global global_ipv4_netfmt wifi_get_ip_info(0, nullptr); @@ -122,9 +122,9 @@ int main (int argc, char* const argv []) { if (!fast) usleep(10000); // not 100% cpu - + loop(); - + // check incoming udp for (auto& udp: udps) { @@ -133,11 +133,10 @@ int main (int argc, char* const argv []) p.events = POLLIN; if (poll(&p, 1, 0) && p.revents == POLLIN) { - fprintf(stderr, MOCK "UDP poll(%d) -> cb\r", (int)p.fd); + fprintf(stderr, MOCK "UDP poll(%d) -> cb\r", p.fd); udp.second->mock_cb(); } } - } return 0; } diff --git a/tests/host/common/ClientContextSocket.cpp b/tests/host/common/ClientContextSocket.cpp index 533d468f5f..b2b6906fd0 100644 --- a/tests/host/common/ClientContextSocket.cpp +++ b/tests/host/common/ClientContextSocket.cpp @@ -73,7 +73,7 @@ size_t mockFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize) if (ret == -1) { if (errno != EAGAIN) - fprintf(stderr, MOCK "ClientContext::(read/peek): filling buffer for %d bytes: %s\n", (int)maxread, strerror(errno)); + fprintf(stderr, MOCK "ClientContext::(read/peek): filling buffer for %zd bytes: %s\n", maxread, strerror(errno)); ret = 0; } return ccinbufsize += ret; @@ -82,7 +82,7 @@ size_t mockFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize) 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 %d bytes (-> %d)\n", CCBUFSIZE, (int)usersize - CCBUFSIZE, (int)usersize); + fprintf(stderr, MOCK "CCBUFSIZE(%d) should be increased by %zd bytes (-> %zd)\n", CCBUFSIZE, usersize - CCBUFSIZE, usersize); struct pollfd p; size_t retsize = 0; @@ -143,7 +143,7 @@ size_t mockWrite (int sock, const uint8_t* data, size_t size, int timeout_ms) } if (ret != (int)size) { - fprintf(stderr, MOCK "ClientContext::write: short write (%d < %d) (TODO)\n", (int)ret, (int)size); + fprintf(stderr, MOCK "ClientContext::write: short write (%d < %zd) (TODO)\n", ret, size); exit(EXIT_FAILURE); } } diff --git a/tests/host/common/MockWire.cpp b/tests/host/common/HostWiring.cpp similarity index 100% rename from tests/host/common/MockWire.cpp rename to tests/host/common/HostWiring.cpp diff --git a/tests/host/common/HardwareSerial.cpp b/tests/host/common/MockSerial.cpp similarity index 100% rename from tests/host/common/HardwareSerial.cpp rename to tests/host/common/MockSerial.cpp diff --git a/tests/host/common/MockTools.cpp b/tests/host/common/MockTools.cpp index 7a89699de2..ca257891b2 100644 --- a/tests/host/common/MockTools.cpp +++ b/tests/host/common/MockTools.cpp @@ -58,8 +58,8 @@ extern "C" void configTime(long timezone, int daylightOffset_sec, (void)server1; (void)server2; (void)server3; - - fprintf(stderr, MOCK "configTime: TODO (tz=%dH offset=%dS) (time will be host's)\n", (int)timezone, daylightOffset_sec); + + fprintf(stderr, MOCK "configTime: TODO (tz=%ldH offset=%dS) (time will be host's)\n", timezone, daylightOffset_sec); } void stack_thunk_add_ref() { } diff --git a/tests/host/common/MockWiFiServerSocket.cpp b/tests/host/common/MockWiFiServerSocket.cpp index b866fdce3c..37ace3bf4c 100644 --- a/tests/host/common/MockWiFiServerSocket.cpp +++ b/tests/host/common/MockWiFiServerSocket.cpp @@ -66,7 +66,7 @@ void WiFiServer::begin () { int sock; struct sockaddr_in server; - + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror(MOCK "socket()"); @@ -79,7 +79,7 @@ void WiFiServer::begin () perror(MOCK "reuseport"); exit(EXIT_FAILURE); } - + server.sin_family = AF_INET; server.sin_port = htons(_port); server.sin_addr.s_addr = htonl(INADDR_ANY); @@ -88,7 +88,7 @@ void WiFiServer::begin () perror(MOCK "bind()"); exit(EXIT_FAILURE); } - + if (listen(sock, 1) == -1) { perror(MOCK "listen()"); @@ -115,7 +115,7 @@ size_t WiFiServer::write (uint8_t c) size_t WiFiServer::write (const uint8_t *buf, size_t size) { - fprintf(stderr, MOCK "todo: WiFiServer::write(%p, %d)\n", buf, (int)size); + fprintf(stderr, MOCK "todo: WiFiServer::write(%p, %zd)\n", buf, size); return 0; } diff --git a/tests/host/common/UdpContextSocket.cpp b/tests/host/common/UdpContextSocket.cpp index fa20f7bd80..d30a6c1246 100644 --- a/tests/host/common/UdpContextSocket.cpp +++ b/tests/host/common/UdpContextSocket.cpp @@ -59,28 +59,28 @@ bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast) fprintf(stderr, MOCK "SO_REUSEADDR failed\n"); struct sockaddr_in servaddr; - memset(&servaddr, 0, sizeof(servaddr)); - - // Filling server information + 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 + + // 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)); + 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, (int)sock); - + 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); @@ -99,7 +99,7 @@ bool mockUDPListen (int sock, uint32_t dstaddr, uint16_t port, uint32_t mcast) return false; } } - + return true; } @@ -114,10 +114,10 @@ size_t mockUDPFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize, uint8_t& if (ret == -1) { if (errno != EAGAIN) - fprintf(stderr, MOCK "UDPContext::(read/peek): filling buffer for %d bytes: %s\n", (int)maxread, strerror(errno)); + 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); @@ -136,7 +136,7 @@ size_t mockUDPFillInBuf (int sock, char* ccinbuf, size_t& ccinbufsize, uint8_t& 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 %d bytes (-> %d)\n", CCBUFSIZE, (int)usersize - CCBUFSIZE, (int)usersize); + fprintf(stderr, MOCK "CCBUFSIZE(%d) should be increased by %zd bytes (-> %zd)\n", CCBUFSIZE, usersize - CCBUFSIZE, usersize); size_t retsize = 0; if (ccinbufsize) @@ -161,7 +161,7 @@ size_t mockUDPRead (int sock, char* dst, size_t size, int timeout_ms, char* ccin size_t mockUDPWrite (int sock, const uint8_t* data, size_t size, int timeout_ms, uint32_t ipv4, uint16_t port) { - // Filling server information + // Filling server information struct sockaddr_in peer; peer.sin_family = AF_INET; peer.sin_addr.s_addr = ipv4; //XXFIXME should use lwip_htonl? @@ -174,7 +174,7 @@ size_t mockUDPWrite (int sock, const uint8_t* data, size_t size, int timeout_ms, } if (ret != (int)size) { - fprintf(stderr, MOCK "UDPContext::write: short write (%d < %d) (TODO)\n", (int)ret, (int)size); + fprintf(stderr, MOCK "UDPContext::write: short write (%d < %zd) (TODO)\n", ret, size); exit(EXIT_FAILURE); } diff --git a/tests/host/common/include/UdpContext.h b/tests/host/common/include/UdpContext.h index 30177f0e71..3ea6f3c67f 100644 --- a/tests/host/common/include/UdpContext.h +++ b/tests/host/common/include/UdpContext.h @@ -111,7 +111,7 @@ class UdpContext fprintf(stderr, MOCK "TODO: implement UDP offset\n"); if (!isValidOffset(pos)) { - fprintf(stderr, MOCK "UDPContext::seek too far (%d >= %d)\n", (int)pos, (int)_inbufsize); + fprintf(stderr, MOCK "UDPContext::seek too far (%zd >= %zd)\n", pos, _inbufsize); exit(EXIT_FAILURE); } } @@ -183,7 +183,7 @@ class UdpContext { if (size + _outbufsize > sizeof _outbuf) { - fprintf(stderr, MOCK "UdpContext::append: increase CCBUFSIZE (%d -> %d)\n", CCBUFSIZE, (int)(size + _outbufsize)); + fprintf(stderr, MOCK "UdpContext::append: increase CCBUFSIZE (%d -> %zd)\n", CCBUFSIZE, (size + _outbufsize)); exit(EXIT_FAILURE); } @@ -200,7 +200,7 @@ class UdpContext _outbufsize = 0; return ret > 0; } - + void mock_cb (void) { if (_on_rx) _on_rx(); @@ -232,14 +232,14 @@ class UdpContext 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]; }; diff --git a/tests/host/common/spiffs_mock.cpp b/tests/host/common/spiffs_mock.cpp index fb8c47692d..e63abae179 100644 --- a/tests/host/common/spiffs_mock.cpp +++ b/tests/host/common/spiffs_mock.cpp @@ -1,14 +1,14 @@ /* spiffs_mock.cpp - SPIFFS HAL mock for host side testing 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. */ @@ -42,7 +42,7 @@ FS SPIFFS(nullptr); SpiffsMock::SpiffsMock(size_t fs_size, size_t fs_block, size_t fs_page, bool storage) { - fprintf(stderr, "SPIFFS: %d bytes\n", (int)fs_size); + fprintf(stderr, "SPIFFS: %zd bytes\n", fs_size); m_storage = storage; m_fs = new uint8_t[m_fs_size = fs_size]; @@ -62,7 +62,7 @@ void SpiffsMock::reset() if (m_storage) load(); } - + SpiffsMock::~SpiffsMock() { if (m_storage) @@ -92,9 +92,9 @@ void SpiffsMock::load () fprintf(stderr, "SPIFFS: loading '%s': %s\n", fname, strerror(errno)); return; } - fprintf(stderr, "SPIFFS: loading %i bytes from '%s'\n", (int)m_fs_size, fname); + 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 %i bytes: %s\n", (int)m_fs_size, strerror(errno)); + fprintf(stderr, "SPIFFS: reading %zi bytes: %s\n", m_fs_size, strerror(errno)); ::close(fs); } @@ -112,13 +112,13 @@ void SpiffsMock::save () fprintf(stderr, "SPIFFS: saving '%s': %s\n", fname, strerror(errno)); return; } - fprintf(stderr, "SPIFFS: saving %i bytes to '%s'\n", (int)m_fs_size, fname); + 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%d:%d ",(int)i, (int)m_fs[i]); +//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 %i bytes: %s\n", (int)m_fs_size, strerror(errno)); + 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)); } From aff3336b8fdfbd07ba0bf493a9b3bd163c9b4084 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Tue, 20 Nov 2018 13:45:59 +0100 Subject: [PATCH 49/50] less verbose makefile by default (option) --- tests/host/Makefile | 38 +++++++++++++++++++------------------- tests/host/README.txt | 2 ++ 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/tests/host/Makefile b/tests/host/Makefile index 8986009e41..667fc15336 100644 --- a/tests/host/Makefile +++ b/tests/host/Makefile @@ -4,6 +4,7 @@ OUTPUT_BINARY := $(BINDIR)/host_tests CORE_PATH := ../../cores/esp8266 FORCE32 ?= 1 OPTZ ?= -Os +V ?= 0 MAKEFILE = $(word 1, $(MAKEFILE_LIST)) @@ -33,6 +34,18 @@ 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)/,\ @@ -167,18 +180,18 @@ build-info: # show toolchain version .SUFFIXES: %.c.o: %.c - $(CC) $(PREINCLUDES) $(CFLAGS) $(INC_PATHS) -MD -MF $(BINDIR)/.$(notdir $<).d -c -o $@ $< + $(VERBC) $(CC) $(PREINCLUDES) $(CFLAGS) $(INC_PATHS) -MD -MF $(BINDIR)/.$(notdir $<).d -c -o $@ $< .PRECIOUS: %.cpp.o %.cpp.o: %.cpp - $(CXX) $(PREINCLUDES) $(CXXFLAGS) $(INC_PATHS) -MD -MF $(BINDIR)/.$(notdir $<).d -c -o $@ $< + $(VERBCXX) $(CXX) $(PREINCLUDES) $(CXXFLAGS) $(INC_PATHS) -MD -MF $(BINDIR)/.$(notdir $<).d -c -o $@ $< $(BINDIR)/core.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE) ar -rcu $@ $^ ranlib -c $@ $(OUTPUT_BINARY): $(CPP_OBJECTS_TESTS) $(BINDIR)/core.a - $(CXX) $(LDFLAGS) $^ -o $@ + $(VERBLD) $(CXX) $(LDFLAGS) $^ -o $@ ################################################# # building ino sources @@ -250,11 +263,11 @@ 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) - ar -rcu $@ $^ - ranlib -c $@ + $(VERBAR) ar -rcu $@ $^ + $(VERBAR) ranlib -c $@ %: %.ino.cpp.o bin/fullcore.a - $(CXX) $(LDFLAGS) $< bin/fullcore.a $(LIBSSL) -o $@ + $(VERBLD) $(CXX) $(LDFLAGS) $< bin/fullcore.a $(LIBSSL) -o $@ @echo "----> $@ <----" ################################################# @@ -283,19 +296,6 @@ $(BINDIR)/$(INO)/$(INO).ino.cpp: endif # recursive ##################### -################################################# -# (debug) - -# https://lists.gnu.org/archive/html/help-make/2002-11/msg00062.html -# Bad gmake, never *ever* try to get a file out of source control by yourself. -#%: %,v -#%: RCS/%,v -#%: RCS/% -#%: s.% -#%: SCCS/s.% - -#Makefile: ; - ################################################# .PHONY: list diff --git a/tests/host/README.txt b/tests/host/README.txt index 475278135b..ca8cfd3179 100644 --- a/tests/host/README.txt +++ b/tests/host/README.txt @@ -34,6 +34,7 @@ run it: ./bin/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) @@ -86,6 +87,7 @@ 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 ? From 49b3e9c90509fd3548c72fc2ea28c58f39e43b88 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Tue, 20 Nov 2018 14:00:14 +0100 Subject: [PATCH 50/50] update readme --- tests/host/README.txt | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/tests/host/README.txt b/tests/host/README.txt index ca8cfd3179..8bc0dac85c 100644 --- a/tests/host/README.txt +++ b/tests/host/README.txt @@ -19,8 +19,8 @@ WiFiClient+WiFiServer/ClientContext and WifiUdp/UdpContext using socket posix API. Further work will optionally propose native lwIP library instead. -How to compile a sketch ------------------------ +How to compile and run a sketch +------------------------------- All results are stored in ./bin/ . @@ -31,7 +31,7 @@ Show the core example list: Build one example make D=1 ../../libraries/esp8266/examples/Blink/Blink run it: - ./bin/Blink -h + ./bin/Blink/Blink -h Optional 'V=1' enables makefile verbosity @@ -66,15 +66,8 @@ Compile other sketches: ./bin/sketch/sketch -Running a sketch ----------------- - -- GPIOs - read as 0(digital) or 512(analog). - output is printed on console. - -Once a sketch is compiled, just run it: - /path/to/your/sketchdir/sketch/sketch +Executable location is always in bin/. Once a sketch is compiled, just run it: + bin/sketch/sketch Options are available: -h @@ -98,3 +91,6 @@ Make fun, propose PRs. - 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.