diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index e917ca55..e64d6750 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -17,16 +17,11 @@ jobs: - uses: actions/setup-python@v2 with: python-version: '3.x' - - name: Cache pip + - name: Cache CMake uses: actions/cache@v2 with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('ci_install.sh') }} - - name: Cache PlatformIO - uses: actions/cache@v2 - with: - path: ~/.platformio - key: ${{ runner.os }}-${{ hashFiles('code/platformio.ini') }} + path: code/test/unit/cache + key: ${{ runner.os }}-${{ hashFiles('code/test/unit/CMakeLists.txt') }} - name: Host tests run: | ./ci_install.sh host diff --git a/ci_install.sh b/ci_install.sh index 9b781730..10ee028f 100755 --- a/ci_install.sh +++ b/ci_install.sh @@ -14,14 +14,13 @@ pio_install() { } host_install() { - pio platform install native + sudo apt install cmake } cd code case "$1" in ("host") - pio_install host_install ;; ("webui") diff --git a/ci_script.sh b/ci_script.sh index 54b77401..91846cd3 100755 --- a/ci_script.sh +++ b/ci_script.sh @@ -6,10 +6,13 @@ cd code case "$1" in ("host") - # runs PIO unit tests, using the host compiler - # (see https://github.com/ThrowTheSwitch/Unity) - pushd test - pio test + # runs unit tests, using the host compiler and the esp8266 mock framework + # - https://github.com/esp8266/Arduino/blob/master/tests/host/Makefile + # - https://github.com/ThrowTheSwitch/Unity + pushd test/unit + cmake -B build + cmake --build build + cmake --build build --target test popd ;; ("webui") diff --git a/code/espurna/tuya_dataframe.h b/code/espurna/tuya_dataframe.h index cba2b5c9..d2ba21a1 100644 --- a/code/espurna/tuya_dataframe.h +++ b/code/espurna/tuya_dataframe.h @@ -129,8 +129,8 @@ public: {} explicit DataFrame(const Transport& input) : - _version(input[2]), - _command(input[3]) + _command(input[3]), + _version(input[2]) { auto length = (input[4] << 8) + input[5]; _data.reserve(length); @@ -141,8 +141,8 @@ public: explicit DataFrame(const DataFrameView& view) : _data(view.cbegin(), view.cend()), - _version(view.version()), - _command(view.command()) + _command(view.command()), + _version(view.version()) {} const container& data() const { @@ -180,8 +180,8 @@ public: private: container _data; - uint8_t _version { 0u }; uint8_t _command { 0u }; + uint8_t _version { 0u }; }; } // namespace diff --git a/code/test/lib/StreamString/StreamString.cpp b/code/test/lib/StreamString/StreamString.cpp deleted file mode 100644 index 4ea857fe..00000000 --- a/code/test/lib/StreamString/StreamString.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/** - StreamString.cpp - - Copyright (c) 2015 Markus Sattler. 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 - - */ - -#include -#include "StreamString.h" - -size_t StreamString::write(const uint8_t *data, size_t size) { - if (!size || !data) return 0; - copy((const char*)data, size + 1); - return size; -} - -size_t StreamString::write(uint8_t data) { - return concat((char) data); -} - -int StreamString::available() { - return length(); -} - -int StreamString::read() { - if(length()) { - char c = charAt(0); - remove(0, 1); - return c; - - } - return -1; -} - -int StreamString::peek() { - if(length()) { - char c = charAt(0); - return c; - } - return -1; -} - -void StreamString::flush() { -} - diff --git a/code/test/lib/StreamString/StreamString.h b/code/test/lib/StreamString/StreamString.h deleted file mode 100644 index 2e81fa14..00000000 --- a/code/test/lib/StreamString/StreamString.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - StreamString.h - - Copyright (c) 2015 Markus Sattler. 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 STREAMSTRING_H_ -#define STREAMSTRING_H_ - - -class StreamString: public Stream, public String { -public: - size_t write(const uint8_t *buffer, size_t size) override; - size_t write(uint8_t data) override; - - int available() override; - int read() override; - int peek() override; - void flush() override; -}; - - -#endif /* STREAMSTRING_H_ */ diff --git a/code/test/lib/test_arduino_compat.h b/code/test/lib/test_arduino_compat.h deleted file mode 100644 index bc9feb2c..00000000 --- a/code/test/lib/test_arduino_compat.h +++ /dev/null @@ -1,5 +0,0 @@ -// some overrides we need when using UnixHostDuino - -#pragma once - -#define strncasecmp_P strncasecmp diff --git a/code/test/platformio.ini b/code/test/platformio.ini deleted file mode 100644 index 13e05d18..00000000 --- a/code/test/platformio.ini +++ /dev/null @@ -1,40 +0,0 @@ -# This file is used compile and run tests located in the `unit` directory. -# For more info, see: -# https://docs.platformio.org/en/latest/plus/unit-testing.html -# https://github.com/ThrowTheSwitch/Unity -# https://github.com/ThrowTheSwitch/Unity/blob/master/docs/UnityAssertionsReference.md - -[platformio] -test_dir = unit -src_dir = ../espurna - -# TODO: add `-t coverage` via python scripting? -# TODO: do we need `-O0`? - -# To prepare coverage data for lcov, add ${coverage.build_flags} to env:test build flags -# To actually generate coverage report: -# $ `pio test` / run the test `program` manually -# $ lcov --include (readlink -f ../espurna)'/*' --capture --directory .pio/build/test/ --output-file test.info -# $ genhtml --ignore-errors source test.info --output-directory out - -[coverage] -build_flags = -lgcov -fprofile-arcs -ftest-coverage - -[env:test] -platform = native -lib_compat_mode = off -test_build_project_src = true -src_filter = - +<../espurna/terminal_commands.cpp> - +<../espurna/terminal_parsing.cpp> -lib_deps = - StreamString - https://github.com/bxparks/UnixHostDuino#d740398e -build_flags = - -DMANUFACTURER="PLATFORMIO" - -DDEVICE="TEST" - -std=gnu++11 - -g - -Os - -include lib/test_arduino_compat.h - -I../espurna/ diff --git a/code/test/unit/CMakeLists.txt b/code/test/unit/CMakeLists.txt new file mode 100644 index 00000000..97af1bed --- /dev/null +++ b/code/test/unit/CMakeLists.txt @@ -0,0 +1,179 @@ +# crude test builder based on +# - https://github.com/esp8266/Arduino/blob/3.0.2/tests/host/Makefile +# - https://github.com/mcspr/rpnlib/blob/0.24.1/examples/host/CMakeLists.txt +# +# we do require certain pre-requisites +# - https://github.com/esp8266/Arduino/ git tree for both Core's and Mock files +# - https://github.com/ThrowTheSwitch/Unity git tree (or tool-unity from platformio) +# +# after everything is installed +# $ cmake -B build +# $ cmake --build build --target test + +cmake_minimum_required(VERSION 3.5) +project(host-test VERSION 1 LANGUAGES C CXX) + +set(CMAKE_C_STANDARD 11 CACHE STRING "Global C standard version (...does not yet work with 17 though)") +set(CMAKE_CXX_STANDARD 17 "Global C++ standard version") + +# required for esp8266 host mocking +set(COMMON_FLAGS + -Os + -g + -fno-common + -funsigned-char + -DCORE_MOCK + -DHOST_MOCK=1 + -DLWIP_IPV6=0 + -Dstrncasecmp_P=strncasecmp +) + +set(ESPURNA_PATH ${CMAKE_SOURCE_DIR}/../../../ CACHE PATH "ESPurna source code repo root") + +# PIO does not really make it easy to install packages outside of the 'platform' context, +# so sharing these between a normal builder might not be an option. (...big TODO though) +# for right now, just fetch these as raw repos. plus, there's no need for any extra params + +set(unity_version v2.5.2) + +include(FetchContent) +FetchContent_Declare( + unitygit + GIT_REPOSITORY https://github.com/ThrowTheSwitch/Unity + GIT_TAG ${unity_version} + GIT_CONFIG core.autocrlf=false core.eol=lf + SOURCE_DIR ${CMAKE_SOURCE_DIR}/cache/unitygit-${unity_version}-src + SUBBUILD_DIR ${CMAKE_SOURCE_DIR}/cache/unitygit-${unity_version}-subbuild +) + +FetchContent_MakeAvailable(unitygit) +FetchContent_GetProperties(unitygit SOURCE_DIR) + +target_compile_options(unity BEFORE PRIVATE + -DUNITY_OUTPUT_COLOR +) + +set(esp8266_version 9fcf14f81fa9be589530e9596b7c5a264dc81ee8) + +FetchContent_Declare( + esp8266git + GIT_REPOSITORY https://github.com/esp8266/Arduino/ + GIT_TAG 9fcf14f81fa9be589530e9596b7c5a264dc81ee8 + GIT_CONFIG core.autocrlf=false core.eol=lf + SOURCE_DIR ${CMAKE_SOURCE_DIR}/cache/esp8266git-${esp8266_version}-src + SUBBUILD_DIR ${CMAKE_SOURCE_DIR}/cache/esp8266git-${esp8266_version}-subbuild +) + +FetchContent_MakeAvailable(esp8266git) +FetchContent_GetProperties(esp8266git SOURCE_DIR) + +# mock'ed Arduino Core headers sometimes expect to be included with some pre-requisites, which we obviously don't have +add_library(common INTERFACE) +target_compile_options(common INTERFACE + "SHELL:-include ${esp8266git_SOURCE_DIR}/tests/host/common/mock.h" + "SHELL:-include ${esp8266git_SOURCE_DIR}/tests/host/common/c_types.h" +) + +# try to hack esp8266 host test layer +# - we need to specify bunch of things that the original Makefile does +# - there are a lot of cross-dependencies, we need to include a lot of .cpp files here +add_library(esp8266 STATIC + src/unity_fixtures.c + src/ArduinoMainOverride.cpp + ${esp8266git_SOURCE_DIR}/tests/host/common/Arduino.cpp + ${esp8266git_SOURCE_DIR}/tests/host/common/ArduinoMainUdp.cpp + ${esp8266git_SOURCE_DIR}/tests/host/common/WMath.cpp + ${esp8266git_SOURCE_DIR}/tests/host/common/MockUART.cpp + ${esp8266git_SOURCE_DIR}/tests/host/common/MockTools.cpp + ${esp8266git_SOURCE_DIR}/tests/host/common/MocklwIP.cpp + ${esp8266git_SOURCE_DIR}/tests/host/common/MockDigital.cpp + ${esp8266git_SOURCE_DIR}/tests/host/common/MockEsp.cpp + ${esp8266git_SOURCE_DIR}/tests/host/common/UdpContextSocket.cpp + ${esp8266git_SOURCE_DIR}/tests/host/common/user_interface.cpp + ${esp8266git_SOURCE_DIR}/tests/host/common/md5.c + ${esp8266git_SOURCE_DIR}/tests/host/common/noniso.c + ${esp8266git_SOURCE_DIR}/tests/host/common/flash_hal_mock.cpp + ${esp8266git_SOURCE_DIR}/tests/host/common/spiffs_mock.cpp + ${esp8266git_SOURCE_DIR}/tests/host/common/littlefs_mock.cpp + ${esp8266git_SOURCE_DIR}/tests/host/common/sdfs_mock.cpp + ${esp8266git_SOURCE_DIR}/tests/host/common/ArduinoMainUdp.cpp + ${esp8266git_SOURCE_DIR}/tests/host/common/ArduinoMainSpiffs.cpp + ${esp8266git_SOURCE_DIR}/tests/host/common/ArduinoMainLittlefs.cpp + ${esp8266git_SOURCE_DIR}/tests/host/common/user_interface.cpp + ${esp8266git_SOURCE_DIR}/cores/esp8266/debug.cpp + ${esp8266git_SOURCE_DIR}/cores/esp8266/core_esp8266_noniso.cpp + ${esp8266git_SOURCE_DIR}/cores/esp8266/stdlib_noniso.cpp + ${esp8266git_SOURCE_DIR}/cores/esp8266/WString.cpp + ${esp8266git_SOURCE_DIR}/cores/esp8266/HardwareSerial.cpp + ${esp8266git_SOURCE_DIR}/cores/esp8266/Print.cpp + ${esp8266git_SOURCE_DIR}/cores/esp8266/Schedule.cpp + ${esp8266git_SOURCE_DIR}/cores/esp8266/time.cpp + ${esp8266git_SOURCE_DIR}/cores/esp8266/Stream.cpp + ${esp8266git_SOURCE_DIR}/cores/esp8266/StreamSend.cpp + ${esp8266git_SOURCE_DIR}/cores/esp8266/FS.cpp + ${esp8266git_SOURCE_DIR}/cores/esp8266/spiffs_api.cpp + ${esp8266git_SOURCE_DIR}/cores/esp8266/spiffs/spiffs_cache.cpp + ${esp8266git_SOURCE_DIR}/cores/esp8266/spiffs/spiffs_check.cpp + ${esp8266git_SOURCE_DIR}/cores/esp8266/spiffs/spiffs_gc.cpp + ${esp8266git_SOURCE_DIR}/cores/esp8266/spiffs/spiffs_hydrogen.cpp + ${esp8266git_SOURCE_DIR}/cores/esp8266/spiffs/spiffs_nucleus.cpp + ${esp8266git_SOURCE_DIR}/libraries/LittleFS/src/LittleFS.cpp + ${esp8266git_SOURCE_DIR}/libraries/LittleFS/src/lfs.c + ${esp8266git_SOURCE_DIR}/libraries/LittleFS/src/lfs_util.c +) +target_include_directories(esp8266 PUBLIC + ${esp8266git_SOURCE_DIR}/tests/host/common/ + ${esp8266git_SOURCE_DIR}/tests/host + ${esp8266git_SOURCE_DIR}/tools/sdk/lwip2/include + ${esp8266git_SOURCE_DIR}/tools/sdk/include + ${esp8266git_SOURCE_DIR}/cores/esp8266/ + ${esp8266git_SOURCE_DIR}/libraries/LittleFS/src/ + ${esp8266git_SOURCE_DIR}/libraries/SPI/ + ${esp8266git_SOURCE_DIR}/libraries/ESP8266SdFat/src +) +target_compile_options(esp8266 PUBLIC + ${COMMON_FLAGS} + -DF_CPU=80000000 + -Wl,--defsym,_FS_start=0x40300000 + -Wl,--defsym,_FS_end=0x411FA000 + -Wl,--defsym,_FS_page=0x100 + -Wl,--defsym,_FS_block=0x2000 + -Wl,--defsym,_EEPROM_start=0x411fb000 +) +target_link_libraries(esp8266 PUBLIC common) + +# our library source (maybe some day this will be a simple glob) +add_library(terminal STATIC + ${ESPURNA_PATH}/code/espurna/terminal_commands.cpp + ${ESPURNA_PATH}/code/espurna/terminal_parsing.cpp +) +target_link_libraries(terminal PUBLIC esp8266) +target_include_directories(terminal PUBLIC + ${ESPURNA_PATH}/code/espurna/ +) +target_compile_options(terminal PUBLIC + ${COMMON_FLAGS} +) +target_compile_options(terminal PRIVATE + -Wall + -Wextra +) + +# each case is built separately, we expect these to work like a normal executable +include(CTest) + +function(build_tests) + foreach(ARG IN LISTS ARGN) + add_executable(test-${ARG} src/${ARG}/${ARG}.cpp) + target_link_libraries(test-${ARG} terminal unity) + target_compile_options(test-${ARG} PRIVATE + ${COMMON_FLAGS} + -Wall + -Wextra + ) + set_target_properties(test-${ARG} PROPERTIES COMPILE_FLAGS -g) + add_test(NAME ${ARG} COMMAND test-${ARG}) + endforeach() +endfunction() + +build_tests(basic settings terminal tuya url) diff --git a/code/test/unit/cache/README.txt b/code/test/unit/cache/README.txt new file mode 100644 index 00000000..a5eee3d9 --- /dev/null +++ b/code/test/unit/cache/README.txt @@ -0,0 +1 @@ +ref. ../CMakeLists.txt diff --git a/code/test/unit/src/ArduinoMainOverride.cpp b/code/test/unit/src/ArduinoMainOverride.cpp new file mode 100644 index 00000000..b2cba983 --- /dev/null +++ b/code/test/unit/src/ArduinoMainOverride.cpp @@ -0,0 +1,325 @@ +// direct c/p from the esp8266/Arduino, just removing the main() since we already call it +// and don't need the rest of the bootstraping done + +/* + 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() + +#include +#include +#include +#include +#include +#include + +#define MOCK_PORT_SHIFTER 9000 + +bool user_exit = false; +bool run_once = false; +const char* host_interface = nullptr; +size_t spiffs_kb = 1024; +size_t littlefs_kb = 1024; +bool ignore_sigint = false; +bool restore_tty = false; +bool mockdebug = false; +int mock_port_shifter = MOCK_PORT_SHIFTER; +const char* fspath = nullptr; + +#define STDIN STDIN_FILENO + +static struct termios initial_settings; + +int mockverbose (const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if (mockdebug) + return fprintf(stderr, MOCK) + vfprintf(stderr, fmt, ap); + return 0; +} + +static int mock_start_uart(void) +{ + struct termios settings; + + if (!isatty(STDIN)) + { + perror("setting tty in raw mode: isatty(STDIN)"); + return -1; + } + if (tcgetattr(STDIN, &initial_settings) < 0) + { + perror("setting tty in raw mode: tcgetattr(STDIN)"); + return -1; + } + settings = initial_settings; + settings.c_lflag &= ~(ignore_sigint ? ISIG : 0); + settings.c_lflag &= ~(ECHO | ICANON); + settings.c_iflag &= ~(ICRNL | INLCR | ISTRIP | IXON); + settings.c_oflag |= (ONLCR); + settings.c_cc[VMIN] = 0; + settings.c_cc[VTIME] = 0; + if (tcsetattr(STDIN, TCSANOW, &settings) < 0) + { + perror("setting tty in raw mode: tcsetattr(STDIN)"); + return -1; + } + restore_tty = true; + return 0; +} + +static int mock_stop_uart(void) +{ + if (!restore_tty) return 0; + if (!isatty(STDIN)) { + perror("restoring tty: isatty(STDIN)"); + return -1; + } + if (tcsetattr(STDIN, TCSANOW, &initial_settings) < 0) + { + perror("restoring tty: tcsetattr(STDIN)"); + return -1; + } + printf("\e[?25h"); // show cursor + return (0); +} + +static uint8_t mock_read_uart(void) +{ + uint8_t ch = 0; + return (read(STDIN, &ch, 1) == 1) ? ch : 0; +} + +void help (const char* argv0, int exitcode) +{ + printf( + "%s - compiled with esp8266/arduino emulator\n" + "options:\n" + "\t-h\n" + "\tnetwork:\n" + "\t-i - use this interface for IP address\n" + "\t-l - bind tcp/udp servers to interface only (not 0.0.0.0)\n" + "\t-s - port shifter (default: %d, when root: 0)\n" + "\tterminal:\n" + "\t-b - blocking tty/mocked-uart (default: not blocking tty)\n" + "\t-T - show timestamp on output\n" + "\tFS:\n" + "\t-P - path for fs-persistent files (default: %s-)\n" + "\t-S - spiffs size in KBytes (default: %zd)\n" + "\t-L - littlefs size in KBytes (default: %zd)\n" + "\t (spiffs, littlefs: negative value will force mismatched size)\n" + "\tgeneral:\n" + "\t-c - ignore CTRL-C (send it via Serial)\n" + "\t-f - no throttle (possibly 100%%CPU)\n" + "\t-1 - run loop once then exit (for host testing)\n" + "\t-v - verbose\n" + , argv0, MOCK_PORT_SHIFTER, argv0, spiffs_kb, littlefs_kb); + exit(exitcode); +} + +static struct option options[] = +{ + { "help", no_argument, NULL, 'h' }, + { "fast", no_argument, NULL, 'f' }, + { "local", no_argument, NULL, 'l' }, + { "sigint", no_argument, NULL, 'c' }, + { "blockinguart", no_argument, NULL, 'b' }, + { "verbose", no_argument, NULL, 'v' }, + { "timestamp", no_argument, NULL, 'T' }, + { "interface", required_argument, NULL, 'i' }, + { "fspath", required_argument, NULL, 'P' }, + { "spiffskb", required_argument, NULL, 'S' }, + { "littlefskb", required_argument, NULL, 'L' }, + { "portshifter", required_argument, NULL, 's' }, + { "once", no_argument, NULL, '1' }, +}; + +void cleanup () +{ + mock_stop_spiffs(); + mock_stop_littlefs(); + mock_stop_uart(); +} + +void make_fs_filename (String& name, const char* fspath, const char* argv0) +{ + name.clear(); + if (fspath) + { + int lastSlash = -1; + for (int i = 0; argv0[i]; i++) + if (argv0[i] == '/') + lastSlash = i; + name = fspath; + name += '/'; + name += &argv0[lastSlash + 1]; + } + else + name = argv0; +} + +void control_c (int sig) +{ + (void)sig; + + if (user_exit) + { + fprintf(stderr, MOCK "stuck, killing\n"); + cleanup(); + exit(1); + } + user_exit = true; +} + +#if 0 +int main (int argc, char* const argv []) +{ + bool fast = false; + blocking_uart = false; // global + + signal(SIGINT, control_c); + signal(SIGTERM, control_c); + if (geteuid() == 0) + mock_port_shifter = 0; + else + mock_port_shifter = MOCK_PORT_SHIFTER; + + for (;;) + { + int n = getopt_long(argc, argv, "hlcfbvTi:S:s:L:P:1", options, NULL); + if (n < 0) + break; + switch (n) + { + case 'h': + help(argv[0], EXIT_SUCCESS); + break; + case 'i': + host_interface = optarg; + break; + case 'l': + global_ipv4_netfmt = NO_GLOBAL_BINDING; + break; + case 's': + mock_port_shifter = atoi(optarg); + break; + case 'c': + ignore_sigint = true; + break; + case 'f': + fast = true; + break; + case 'S': + spiffs_kb = atoi(optarg); + break; + case 'L': + littlefs_kb = atoi(optarg); + break; + case 'P': + fspath = optarg; + break; + case 'b': + blocking_uart = true; + break; + case 'v': + mockdebug = true; + break; + case 'T': + serial_timestamp = true; + break; + case '1': + run_once = true; + break; + default: + help(argv[0], EXIT_FAILURE); + } + } + + mockverbose("server port shifter: %d\n", mock_port_shifter); + + if (spiffs_kb) + { + String name; + make_fs_filename(name, fspath, argv[0]); + name += "-spiffs"; + name += String(spiffs_kb > 0? spiffs_kb: -spiffs_kb, DEC); + name += "KB"; + mock_start_spiffs(name, spiffs_kb); + } + + if (littlefs_kb) + { + String name; + make_fs_filename(name, fspath, argv[0]); + name += "-littlefs"; + name += String(littlefs_kb > 0? littlefs_kb: -littlefs_kb, DEC); + name += "KB"; + mock_start_littlefs(name, littlefs_kb); + } + + // setup global global_ipv4_netfmt + wifi_get_ip_info(0, nullptr); + + if (!blocking_uart) + { + // set stdin to non blocking mode + mock_start_uart(); + } + + // install exit handler in case Esp.restart() is called + atexit(cleanup); + + // first call to millis(): now is millis() and micros() beginning + millis(); + + setup(); + while (!user_exit) + { + uint8_t data = mock_read_uart(); + + if (data) + uart_new_data(UART0, data); + if (!fast) + usleep(1000); // not 100% cpu, ~1000 loops per second + loop(); + loop_end(); + check_incoming_udp(); + + if (run_once) + user_exit = true; + } + cleanup(); + + return 0; +} +#endif diff --git a/code/test/unit/basic/basic.cpp b/code/test/unit/src/basic/basic.cpp similarity index 82% rename from code/test/unit/basic/basic.cpp rename to code/test/unit/src/basic/basic.cpp index 7ecf5eef..c8112344 100644 --- a/code/test/unit/basic/basic.cpp +++ b/code/test/unit/src/basic/basic.cpp @@ -9,8 +9,8 @@ void test_linkage() { pinMode(0, OUTPUT); } -int main(int argc, char** argv) { +int main(int, char**) { UNITY_BEGIN(); RUN_TEST(test_linkage); - UNITY_END(); + return UNITY_END(); } diff --git a/code/test/unit/settings/main.cpp b/code/test/unit/src/settings/settings.cpp similarity index 99% rename from code/test/unit/settings/main.cpp rename to code/test/unit/src/settings/settings.cpp index 1f6dc8b4..a301cda2 100644 --- a/code/test/unit/settings/main.cpp +++ b/code/test/unit/src/settings/settings.cpp @@ -477,7 +477,7 @@ void test_keys_iterator() { } -int main(int argc, char** argv) { +int main(int, char**) { UNITY_BEGIN(); RUN_TEST(test_storage); RUN_TEST(test_keys_iterator); diff --git a/code/test/unit/terminal/terminal.cpp b/code/test/unit/src/terminal/terminal.cpp similarity index 98% rename from code/test/unit/terminal/terminal.cpp rename to code/test/unit/src/terminal/terminal.cpp index 94995f0a..1742dffa 100644 --- a/code/test/unit/terminal/terminal.cpp +++ b/code/test/unit/src/terminal/terminal.cpp @@ -216,10 +216,10 @@ void test_quotes() { void test_case_insensitive() { - terminal::Terminal::addCommand(F("test.lowercase1"), [](::terminal::CommandContext&& ctx) { + terminal::Terminal::addCommand(F("test.lowercase1"), [](::terminal::CommandContext&&) { TEST_FAIL_MESSAGE("`test.lowercase1` was registered first, but there's another function by the same name. This should not be called"); }); - terminal::Terminal::addCommand(F("TEST.LOWERCASE1"), [](::terminal::CommandContext&& ctx) { + terminal::Terminal::addCommand(F("TEST.LOWERCASE1"), [](::terminal::CommandContext&&) { __asm__ volatile ("nop"); }); @@ -252,7 +252,7 @@ void test_output() { // When adding test functions, don't forget to add RUN_TEST(...) in the main() -int main(int argc, char** argv) { +int main(int, char**) { UNITY_BEGIN(); RUN_TEST(test_command); RUN_TEST(test_command_args); @@ -262,5 +262,5 @@ int main(int argc, char** argv) { RUN_TEST(test_quotes); RUN_TEST(test_case_insensitive); RUN_TEST(test_output); - UNITY_END(); + return UNITY_END(); } diff --git a/code/test/unit/tuya/tuya.cpp b/code/test/unit/src/tuya/tuya.cpp similarity index 99% rename from code/test/unit/tuya/tuya.cpp rename to code/test/unit/src/tuya/tuya.cpp index 869eb7c7..5248cf41 100644 --- a/code/test/unit/tuya/tuya.cpp +++ b/code/test/unit/src/tuya/tuya.cpp @@ -298,7 +298,7 @@ void test_dataframe_echo() { } } -int main(int argc, char** argv) { +int main(int, char**) { UNITY_BEGIN(); diff --git a/code/test/unit/src/unity_fixtures.c b/code/test/unit/src/unity_fixtures.c new file mode 100644 index 00000000..edca66d0 --- /dev/null +++ b/code/test/unit/src/unity_fixtures.c @@ -0,0 +1,14 @@ +// minimal set of functions that are supposed to be linked with the unity.c + +void setUp(void) { +} + +void tearDown(void) { +} + +void suiteSetUp(void) { +} + +int suiteTearDown(int failures) { + return failures; +} diff --git a/code/test/unit/url/url.cpp b/code/test/unit/src/url/url.cpp similarity index 86% rename from code/test/unit/url/url.cpp rename to code/test/unit/src/url/url.cpp index a0c4fe9b..43fa6511 100644 --- a/code/test/unit/url/url.cpp +++ b/code/test/unit/src/url/url.cpp @@ -10,12 +10,8 @@ void test_parse() { TEST_ASSERT_EQUAL(80, url.port); } -int main(int argc, char** argv) { - +int main(int, char**) { UNITY_BEGIN(); - RUN_TEST(test_parse); - - UNITY_END(); - + return UNITY_END(); }