1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-06 05:21:22 +03:00

Device tests updates (#9246)

Stop pyexpect from closing serial port when running with WSL2
Remove makefile flags & opts making it too silent. At some point it makes a lot of useful info just disappear. There are external means of silencing make, so probably best to leave useful data always available

Replace SPIFFS with LittleFS in FS test
Re-use certs-from-mozilla.py in FS test

Fix libc tests w/o -fno-builtin not actually testing anything, also add the flag via .globals.h in case it breaks
Fix libc tests generating warnings when using invalid (but safe) size arguments
This commit is contained in:
Max Prokhorov 2025-05-21 16:21:08 +03:00 committed by GitHub
parent a5f18b5f91
commit 92002ece2e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 408 additions and 322 deletions

View File

@ -13,15 +13,9 @@ import os
import sys
from shutil import which
from subprocess import Popen, PIPE, call
try:
from urllib.request import urlopen
except Exception:
from urllib2 import urlopen
try:
from StringIO import StringIO
except Exception:
from io import StringIO
from io import StringIO
from subprocess import Popen, PIPE, call, CalledProcessError
from urllib.request import urlopen
# check if ar and openssl are available
if which('ar') is None and not os.path.isfile('./ar') and not os.path.isfile('./ar.exe'):
@ -62,10 +56,10 @@ for i in range(0, len(pems)):
thisPem = pems[i].replace("'", "")
print(names[i] + " -> " + certName)
ssl = Popen(['openssl','x509','-inform','PEM','-outform','DER','-out', certName], shell = False, stdin = PIPE)
pipe = ssl.stdin
pipe.write(thisPem.encode('utf-8'))
pipe.close()
ssl.wait()
ssl.communicate(thisPem.encode('utf-8'))
ret = ssl.wait()
if ret != 0:
raise CalledProcessError(ret, certName)
if os.path.exists(certName):
derFiles.append(certName)
idx = idx + 1

View File

@ -1,45 +1,65 @@
SHELL := /bin/bash
V ?= 0
ESP8266_CORE_PATH ?= $(realpath ../..)
BUILD_DIR ?= $(PWD)/.build
HARDWARE_DIR ?= $(PWD)/.hardware
ESP8266_CORE_PATH ?= $(shell git rev-parse --show-toplevel)
BUILD_DIR ?= $(PWD)/build
BS_DIR ?= $(PWD)/libraries/BSTest
PYTHON ?= python3
ESPTOOL ?= $(PYTHON) $(ESP8266_CORE_PATH)/tools/esptool/esptool.py
MKSPIFFS ?= $(ESP8266_CORE_PATH)/tools/mkspiffs/mkspiffs
VENV_PYTHON ?= $(BS_DIR)/virtualenv/bin/python
VENV_JUNIT2HTML ?= $(BS_DIR)/virtualenv/bin/junit2html
MKFS ?= $(ESP8266_CORE_PATH)/tools/mklittlefs/mklittlefs
UPLOAD_PORT ?= $(shell ls /dev/tty* | grep -m 1 -i USB)
UPLOAD_BAUD ?= 460800
UPLOAD_BOARD ?= nodemcu
BS_DIR ?= libraries/BSTest
DEBUG_LEVEL ?= lvl=None____
FQBN ?= esp8266com:esp8266:generic:xtal=160,FlashFreq=40,FlashMode=dio,baud=115200,eesz=4M1M,ip=lm2f,ResetMethod=nodemcu,dbg=Serial,$(DEBUG_LEVEL)
BUILD_TOOL := $(ARDUINO_IDE_PATH)/arduino-builder
TEST_BAUD ?= 115200
BUILD_TOOL ?= arduino-cli
BUILD_BOARD ?= generic
BUILD_CPU ?= 160
BUILD_SIZE ?= 4M1M
BUILD_LWIP ?= lm2f
BUILD_EXTRA ?= ,dbg=Serial,lvl=CORE
FQBN ?= esp8266com:esp8266:$(BUILD_BOARD):xtal=$(BUILD_CPU),baud=$(TEST_BAUD),eesz=$(BUILD_SIZE),ip=$(BUILD_LWIP)$(BUILD_EXTRA)
TEST_CONFIG := test_env.cfg
TEST_RESULT_XML := test_result.xml
TEST_REPORT_XML := test_report.xml
TEST_REPORT_HTML := test_report.html
ifeq ("$(MOCK)", "1")
# To enable a test for mock testing, just rename dir+files to '*_sw_*'
TEST_LIST ?= $(wildcard test_sw_*/*.ino)
else
TEST_LIST ?= $(wildcard test_*/*.ino)
BUILD_FLAGS ?=
BS_FLAGS ?=
# To enable a test for mock testing, just rename dir+files to '*_sw_*'
ifeq ("$(MOCK)", "1")
TEST_LIST := $(filter test_sw_%.ino,$(TEST_LIST))
NO_UPLOAD := 1
NO_RUN := 1
endif
ifneq ("$(V)","1")
SILENT = @
REDIR = >& /dev/null
else
BUILDER_DEBUG_FLAG = -verbose
RUNNER_DEBUG_FLAG = -d
#UPLOAD_VERBOSE_FLAG = -v
# To enable verbose mode, call `make V=1` ...
V ?= 0
ifeq ("$(V)", "1")
BUILD_FLAGS += --verbose
BS_FLAGS += --debug
endif
# ${sketch}.py helper script when building locally
mock_script = \
`test -f $(addsuffix .py, $(basename $(1))) && echo "--mock $(addsuffix .py, $(basename $(1)))" || echo ""`
help:
@echo
@echo 'make list - show list of tests'
@echo 'make sometest/sometest.ino - run one test'
@echo 'make all - run all tests'
@echo 'make MOCK=1 all - run all emulation-on-host compatible tests'
@echo 'variables needed: $$ARDUINO_IDE_PATH $$ESP8266_CORE_PATH'
@echo 'make options: V=1 NO_BUILD=1 NO_UPLOAD=1 NO_RUN=1 MOCK=1'
@echo
@ -49,110 +69,132 @@ all: count tests test_report
$(TEST_LIST): | virtualenv $(TEST_CONFIG) $(BUILD_DIR) $(HARDWARE_DIR)
.NOTPARALLEL: $(TEST_LIST)
tests: showtestlist $(TEST_LIST)
showtestlist:
@echo "-------------------------------- test list:"
@echo $(TEST_LIST)
@printf '%s\n' $(TEST_LIST)
@echo "--------------------------------"
$(TEST_LIST): LOCAL_BUILD_DIR=$(BUILD_DIR)/$(notdir $@)
$(TEST_LIST): LOCAL_DATA_IMG=data.img
$(TEST_LIST):
@echo "--------------------------------"
@echo "Running test '$@' of $(words $(TEST_LIST)) tests"
$(SILENT)mkdir -p $(LOCAL_BUILD_DIR)
ifeq ("$(MOCK)", "1")
@echo Compiling $(notdir $@)
(cd ../host; make D=$(V) ULIBDIRS=../device/libraries/BSTest ../device/$(@:%.ino=%))
$(SILENT)$(BS_DIR)/virtualenv/bin/python \
$(BS_DIR)/runner.py \
$(RUNNER_DEBUG_FLAG) \
-e "$(ESP8266_CORE_PATH)/tests/host/bin/$(@:%.ino=%)" \
-n $(basename $(notdir $@)) \
-o $(LOCAL_BUILD_DIR)/test_result.xml \
--env-file $(TEST_CONFIG) \
`test -f $(addsuffix .py, $(basename $@)) && echo "-m $(addsuffix .py, $(basename $@))" || echo ""`
else
ifneq ("$(NO_BUILD)","1")
@test -n "$(ARDUINO_IDE_PATH)" || (echo "Please export ARDUINO_IDE_PATH" && exit 1)
@echo Compiling $(notdir $@)
@rm -f $(LOCAL_BUILD_DIR)/build.options.json
$(SILENT)$(BUILD_TOOL) -compile -logger=human \
-libraries "$(PWD)/libraries" \
-core-api-version="10608" \
-warnings=all \
$(BUILDER_DEBUG_FLAG) \
-build-path $(LOCAL_BUILD_DIR) \
-tools $(ARDUINO_IDE_PATH)/tools-builder \
-hardware $(HARDWARE_DIR)\
-hardware $(ARDUINO_IDE_PATH)/hardware \
-fqbn=$(FQBN) \
define build-arduino
rm -f $(LOCAL_BUILD_DIR)/build.options.json
$(BUILD_TOOL) compile \
$(BUILD_FLAGS) \
--libraries "$(PWD)/libraries" \
--warnings=all \
--build-path $(LOCAL_BUILD_DIR) \
--fqbn=$(FQBN) \
$@
endif
ifneq ("$(NO_UPLOAD)","1")
@test -n "$(UPLOAD_PORT)" || (echo "Failed to detect upload port, please export UPLOAD_PORT manually" && exit 1)
@test -e $(dir $@)/make_spiffs.py && ( \
echo "Generating and uploading SPIFFS" && \
(cd $(dir $@) && $(PYTHON) ./make_spiffs.py $(REDIR) ) && \
$(MKSPIFFS) --create $(dir $@)data/ --size 0xFB000 \
--block 8192 --page 256 $(LOCAL_BUILD_DIR)/spiffs.img $(REDIR) && \
$(ESPTOOL) $(UPLOAD_VERBOSE_FLAG) \
endef
define build-mock
(cd $(ESP8266_CORE_PATH)/test/host; \
$(MAKE) D=$(V) ULIBDIRS=$(PWD)/libraries/BSTest $(PWD)/$(@:%.ino=%))
$(VENV_PYTHON) $(BS_DIR)/runner.py \
$(BS_FLAGS) \
--name $(basename $(notdir $@)) \
--output $(LOCAL_BUILD_DIR)/$(TEST_RESULT_XML) \
--env-file $(TEST_CONFIG) \
$(call mock_script,$@) \
executable "$(ESP8266_CORE_PATH)/tests/host/bin/$(@:%.ino=%)" || echo ""`
endef
define upload-data
@test -n "$(UPLOAD_PORT)" \
|| (echo "Failed to detect upload port, please export UPLOAD_PORT manually" && exit 1)
@test ! \( -d $(dir $@)/data/ \) -a \( -e $(dir $@)/make_data.py \) && \
(cd $(dir $@) && ./make_data.py ) || echo "Filesystem creation skipped"
@test -d $(dir $@)/data/ && ( \
$(MKFS) \
--create $(dir $@)/data/ \
--size 0xFB000 \
--block 8192 \
--page 256 \
$(LOCAL_BUILD_DIR)/$(LOCAL_DATA_IMG) && \
$(ESPTOOL) \
--chip esp8266 \
--port $(UPLOAD_PORT) \
--baud $(UPLOAD_BAUD) \
--after no_reset \
write_flash 0x300000 $(LOCAL_BUILD_DIR)/spiffs.img $(REDIR) ) \
|| (echo "No SPIFFS to upload")
@echo Uploading binary
$(SILENT)$(ESPTOOL) $(UPLOAD_VERBOSE_FLAG) \
write_flash 0x300000 $(LOCAL_BUILD_DIR)/$(LOCAL_DATA_IMG) ) \
&& (echo "Uploaded filesystem") \
|| (echo "Filesystem upload skipped")
endef
define upload-binary
@test -n "$(UPLOAD_PORT)" \
|| (echo "Failed to detect upload port, please export UPLOAD_PORT manually" && exit 1)
$(ESPTOOL) \
--chip esp8266 \
--port $(UPLOAD_PORT) \
--baud $(UPLOAD_BAUD) \
--after no_reset \
write_flash 0x0 $(LOCAL_BUILD_DIR)/$(notdir $@).bin $(REDIR) # no reset
endif
ifneq ("$(NO_RUN)","1")
@test -n "$(UPLOAD_PORT)" || (echo "Failed to detect upload port, please export UPLOAD_PORT manually" && exit 1)
write_flash 0x0 $(LOCAL_BUILD_DIR)/$(notdir $@).bin
endef
define run-test
@test -n "$(UPLOAD_PORT)" \
|| (echo "Failed to detect upload port, please export UPLOAD_PORT manually" && exit 1)
@echo Running tests
$(SILENT)$(ESPTOOL) $(UPLOAD_VERBOSE_FLAG) \
$(ESPTOOL) \
--chip esp8266 \
--port $(UPLOAD_PORT) \
--baud $(UPLOAD_BAUD) \
read_flash_status $(REDIR) # reset
$(SILENT)$(BS_DIR)/virtualenv/bin/python \
$(BS_DIR)/runner.py \
$(RUNNER_DEBUG_FLAG) \
-p $(UPLOAD_PORT) \
-n $(basename $(notdir $@)) \
-o $(LOCAL_BUILD_DIR)/test_result.xml \
--env-file $(TEST_CONFIG) \
`test -f $(addsuffix .py, $(basename $@)) && echo "-m $(addsuffix .py, $(basename $@))" || echo ""`
read_flash_status # reset via implicit stub reboot
$(VENV_PYTHON) $(BS_DIR)/runner.py \
$(BS_FLAGS) \
--name $(basename $(notdir $@)) \
--output $(LOCAL_BUILD_DIR)/$(TEST_RESULT_XML) \
--env-file $(TEST_CONFIG) \
$(call mock_script,$@) \
port $(UPLOAD_PORT) \
--baudrate $(TEST_BAUD)
endef
$(TEST_LIST):
@echo "--------------------------------"
@echo "Running test '$@' of $(words $(TEST_LIST)) tests"
mkdir -p $(LOCAL_BUILD_DIR)
ifneq ("$(NO_BUILD)","1")
@echo Building $(notdir $@)
ifeq ("$(MOCK)", "1")
$(build-mock)
else
$(build-arduino)
endif
endif
ifneq ("$(NO_UPLOAD)","1")
$(upload-filesystem)
$(upload-binary)
endif
ifneq ("$(NO_RUN)","1")
$(run-test)
endif
$(TEST_REPORT_XML): $(HARDWARE_DIR) virtualenv
$(SILENT)$(BS_DIR)/xunitmerge $(shell find $(BUILD_DIR) -name 'test_result.xml' | xargs echo) $(TEST_REPORT_XML)
$(TEST_REPORT_XML): virtualenv
$(BS_DIR)/xunitmerge \
$(shell find $(BUILD_DIR) -name '$(TEST_RESULT_XML)' | xargs echo) \
$(TEST_REPORT_XML)
$(TEST_REPORT_HTML): $(TEST_REPORT_XML) | virtualenv
$(SILENT)$(BS_DIR)/virtualenv/bin/junit2html $< $@
$(VENV_JUNIT2HTML) $< $@
test_report: $(TEST_REPORT_HTML)
@echo "Test report generated in $(TEST_REPORT_HTML)"
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)
$(HARDWARE_DIR):
mkdir -p $(HARDWARE_DIR)/esp8266com
cd $(HARDWARE_DIR)/esp8266com && ln -s $(realpath $(ESP8266_CORE_PATH)) esp8266
@mkdir -p $(BUILD_DIR)
virtualenv:
@make -C $(BS_DIR) PYTHON=$(PYTHON) virtualenv
clean:
rm -rf $(BUILD_DIR)
rm -rf $(HARDWARE_DIR)
rm -rf $(BS_DIR)/virtualenv
rm -f $(TEST_REPORT_HTML) $(TEST_REPORT_XML)

View File

@ -1,40 +1,32 @@
#!/usr/bin/env python3
from __future__ import print_function
import serial
import pexpect
from pexpect import EOF, TIMEOUT, fdpexpect
import sys
import os
import time
import argparse
import serial
import subprocess
from importlib.machinery import SourceFileLoader
try:
from configparser import ConfigParser
except:
from ConfigParser import ConfigParser
import itertools
try:
from urllib.parse import urlparse, urlencode
except ImportError:
from urlparse import urlparse
from junit_xml import TestSuite, TestCase
try:
from cStringIO import StringIO
except:
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
import argparse
import itertools
import os
import subprocess
import sys
import time
from configparser import ConfigParser
from importlib.machinery import SourceFileLoader
from io import StringIO
from urllib.parse import urlparse, urlencode
import mock_decorators
debug = False
#debug = True
sys.path.append(os.path.abspath(__file__))
IS_WSL = len(os.environ.get("WSL_DISTRO_NAME", "")) > 0
def debug_print(*args, **kwargs):
if not debug:
return
@ -235,9 +227,11 @@ class BSTestRunner(object):
ser = None
def spawn_port(port_name, baudrate=115200):
def spawn_port(port_name, baudrate=115200, close=True):
global ser
ser = serial.serial_for_url(port_name, baudrate=baudrate)
if not close:
ser.close = lambda: None
return fdpexpect.fdspawn(ser, 'wb', timeout=0, encoding='cp437')
def spawn_exec(name):
@ -250,30 +244,39 @@ def run_tests(spawn, name, mocks, env_vars):
def parse_args():
parser = argparse.ArgumentParser(description='BS test runner')
parser.add_argument('-d', '--debug', help='Send test output to stderr', action='store_true')
parser.add_argument('-p', '--port', help='Talk to the test over serial')
parser.add_argument('-e', '--executable', help='Talk to the test executable')
parser.add_argument('-n', '--name', help='Test run name')
parser.add_argument('-o', '--output', help='Output JUnit format test report')
parser.add_argument('-m', '--mock', help='Set python script to use for mocking purposes')
parser.add_argument('--debug', help='Send test output to stderr', action='store_true')
parser.add_argument('--name', help='Test run name')
parser.add_argument('--output', help='Output JUnit format test report')
parser.add_argument('--mock', help='Set python script to use for mocking purposes')
parser.add_argument('--env-file', help='File containing a list of environment variables to set', type=argparse.FileType('r'))
sub = parser.add_subparsers()
def as_spawn_port(args):
return spawn_port(args.port, args.baudrate, args.close)
port = sub.add_parser('port')
port.add_argument('port', type=str)
port.add_argument('--baudrate', help='Serial port baudrate', type=int, default=115200)
port.add_argument('--close', help='Close serial port after the test', action=argparse.BooleanOptionalAction, default=not IS_WSL)
port.set_defaults(func=as_spawn_port)
def as_spawn_exec(args):
return spawn_exec(args.executable)
exe = sub.add_parser('executable')
exe.add_argument('executable', help='Talk to the test executable')
exe.set_defaults(func=as_spawn_exec)
return parser.parse_args()
def main():
args = parse_args()
spawn_func = None
spawn_arg = None
if args.port is not None:
spawn_func = spawn_port
spawn_arg = args.port
elif args.executable is not None:
spawn_func = spawn_exec
spawn_arg = args.executable
name = args.name or ""
global debug
if args.debug:
debug = True
if spawn_func is None:
debug = args.debug
if args.func is None:
debug_print("Please specify port or executable", file=sys.stderr)
return 1
env_vars = []
@ -287,7 +290,8 @@ def main():
if args.mock is not None:
mocks_mod = SourceFileLoader('mocks', args.mock).load_module()
mocks = mock_decorators.env
with spawn_func(spawn_arg) as sp:
with args.func(args) as sp:
ts = run_tests(sp, name, mocks, env_vars)
if args.output:
with open(args.output, "w") as f:

View File

@ -0,0 +1 @@
../../../libraries/ESP8266WiFi/examples/BearSSL_CertStore/certs-from-mozilla.py

View File

@ -1,71 +0,0 @@
#!/usr/bin/python3
# This script pulls the list of Mozilla trusted certificate authorities
# from the web at the "mozurl" below, parses the file to grab the PEM
# for each cert, and then generates DER files in a new ./data directory
# Upload these to a SPIFFS filesystem and use the CertManager to parse
# and use them for your outgoing SSL connections.
#
# Script by Earle F. Philhower, III. Released to the public domain.
from __future__ import print_function
import csv
import os
import sys
from subprocess import Popen, PIPE, call
try:
from urllib.request import urlopen
except:
from urllib2 import urlopen
try:
from StringIO import StringIO
except:
from io import StringIO
# Mozilla's URL for the CSV file with included PEM certs
mozurl = "https://ccadb-public.secure.force.com/mozilla/IncludedCACertificateReportPEMCSV"
# Load the manes[] and pems[] array from the URL
names = []
pems = []
response = urlopen(mozurl)
csvData = response.read()
if sys.version_info[0] > 2:
csvData = csvData.decode('utf-8')
csvFile = StringIO(csvData)
csvReader = csv.reader(csvFile)
for row in csvReader:
names.append(row[0]+":"+row[1]+":"+row[2])
pems.append(row[30])
del names[0] # Remove headers
del pems[0] # Remove headers
# Try and make ./data, skip if present
try:
os.mkdir("data")
except:
pass
derFiles = []
idx = 0
# Process the text PEM using openssl into DER files
for i in range(0, len(pems)):
certName = "data/ca_%03d.der" % (idx);
thisPem = pems[i].replace("'", "")
print(names[i] + " -> " + certName)
ssl = Popen(['openssl','x509','-inform','PEM','-outform','DER','-out', certName], shell = False, stdin = PIPE)
pipe = ssl.stdin
pipe.write(thisPem.encode('utf-8'))
pipe.close()
ssl.wait()
if os.path.exists(certName):
derFiles.append(certName)
idx = idx + 1
if os.path.exists("data/certs.ar"):
os.unlink("data/certs.ar");
arCmd = ['ar', 'q', 'data/certs.ar'] + derFiles;
call( arCmd )
for der in derFiles:
os.unlink(der)

View File

@ -1,7 +1,7 @@
// Stress test the BearSSL connection options to determine
// maximum memory use for different SSL connections and
// SPIFFS certstore usage. Before running you need to run
// certs-from-mozilla.py and upload the generated SPIFFS file.
// filesystem certstore usage. Before running the test you need to
// update them with certs-from-mozilla.py and upload the generated file.
//
// For more info on CertStores, see the BearSSL_CertStore example
//
@ -12,7 +12,7 @@
#include <BSTest.h>
#include <ESP8266WiFi.h>
#include <CertStoreBearSSL.h>
#include <FS.h>
#include <LittleFS.h>
#include <time.h>
#include <StackThunk.h>
@ -45,11 +45,11 @@ bool pretest()
delay(500);
}
setClock();
SPIFFS.begin();
int numCerts = certStore.initCertStore(SPIFFS, "/certs.idx", "/certs.ar");
LittleFS.begin();
int numCerts = certStore.initCertStore(LittleFS, "/certs.idx", "/certs.ar");
Serial.printf("Number of CA certs read: %d\n", numCerts);
if (numCerts == 0) {
Serial.printf("No certs found. Did you run certs-from-mozill.py and upload the SPIFFS directory before running?\n");
Serial.printf("No certs found. Did you run upload script?\n");
return false;
}
return true;

View File

@ -3,51 +3,130 @@
#include <stdlib.h>
#include <errno.h>
#define memcmp memcmp_P
#define memcpy memcpy_P
#define memmem memmem_P
#define memchr memchr_P
#define strcat strcat_P
#define strncat strncat_P
#define strcpy strcpy_P
#define strncpy strncpy_P
#define strlen strlen_P
#define strnlen strnlen_P
#define strcmp strcmp_P
#define strncmp strncmp_P
#include <sys/pgmspace.h>
_CONST char* it = "<UNSET>"; /* Routine name for message routines. */
/* esp8266/Arduino note
*
* Prevent the compiler from
* - solving test cases below at compile time, effectively removing any checks
* - optimizing out libc func calls, replacing them with bytewise memory access
*
* Plus, test framework cannot pass -fno-builtin-... per-file, only globally
*/
#define xDST_SRC_N(T, NAME)\
static T* __attribute__((used, noinline)) x ## NAME (T* dst, const T* src, size_t n)\
{\
return NAME (dst, src, n);\
}
xDST_SRC_N (void, memcpy)
xDST_SRC_N (void, memmove)
xDST_SRC_N (char, strncat)
xDST_SRC_N (char, strncpy)
#define xDST_SRC(T, NAME)\
static T* __attribute__((used, noinline)) x ## NAME (T* dst, const T* src)\
{\
return NAME (dst, src);\
}
xDST_SRC (char, strcat)
xDST_SRC (char, strcpy)
#define xS1_S2_N(RET, T, NAME)\
static RET __attribute__((used, noinline)) x ## NAME (const T *s1, const T *s2, size_t n)\
{\
return NAME (s1, s2, n);\
}
xS1_S2_N(int, void, memcmp)
xS1_S2_N(int, char, strncmp)
static int __attribute__((used, noinline)) xstrcmp (const char *s1, const char *s2)
{
return strcmp (s1, s2);
}
static void* __attribute__((used, noinline)) xmemchr (const void* s, int c, size_t n)
{
return memchr (s, c, n);
}
static size_t __attribute__((used, noinline)) xstrlen (const char* s)
{
return strlen (s);
}
#if 0
/* TODO remove when libc supports pointers to flash */
#undef PSTR
#define PSTR(X) X
#define memcmp(s1,s2,n) xmemcmp(s1,PSTR(s2),n)
#define memcpy(dest,src,n) xmemcpy(dest,PSTR(src),n)
#define memmove(dest,src,n) xmemmove(dest,PSTR(src),n)
#define memchr(s,c,n) xmemchr(PSTR(s),c,n)
#define strcat(dst,src) xstrcat(dst,PSTR(src))
#define strncat(dst,src,ssize) xstrncat(dst,PSTR(src),ssize)
#define strcpy(dst,src) xstrcpy(dst,PSTR(src))
#define strncpy(dst,src,dsize) xstrncpy(dst,PSTR(src),dsize)
#define strlen(s) xstrlen(PSTR(s))
#define strcmp(s1,s2) xstrcmp(s1,PSTR(s2))
#define strncmp(s1,s2,n) xstrncmp(s1,PSTR(s2),n)
#else
/* in case wrapped calls are not required */
#define memcmp(s1,s2,n) memcmp_P(s1,PSTR(s2),n)
#define memcpy(dest,src,n) memcpy_P(dest,PSTR(src),n)
#define memmove(dest,src,n) memmove_P(dest,PSTR(src),n)
#define memchr(s,c,n) memchr_P(PSTR(s),c,n)
#define strcat(dst,src) strcat_P(dst,PSTR(src))
#define strncat(dst,src,ssize) strncat_P(dst,PSTR(src),ssize)
#define strcpy(dst,src) strcpy_P(dst,PSTR(src))
#define strncpy(dst,src,dsize) strncpy_P(dst,PSTR(src),dsize)
#define strlen(s) strlen_P(PSTR(s))
#define strcmp(s1,s2) strcmp_P(s1,PSTR(s2))
#define strncmp(s1,s2,n) strncmp_P(s1,PSTR(s2),n)
#endif
static const char Unset[] PROGMEM = "<UNSET>";
const char* it = Unset; /* Routine name for message routines. */
static int errors = 0;
/* Complain if condition is not true. */
#define check(thing) checkit(thing, __LINE__)
static void _DEFUN(checkit, (ok, l), int ok _AND int l)
static void checkit(int ok, int l)
{
// newfunc(it);
// line(l);
if (!ok)
{
printf("string.c:%d %s\n", l, it);
printf(PSTR("string.c:%d %s\n"), l, it);
++errors;
}
}
/* Complain if first two args don't strcmp as equal. */
#define equal(a, b) funcqual(a, b, __LINE__);
#define equal(a, b) funcqual(a, PSTR(b), __LINE__);
static void _DEFUN(funcqual, (a, b, l), char* a _AND char* b _AND int l)
static void funcqual(const char *a, const char *b, int l)
{
// newfunc(it);
// line(l);
if (a == NULL && b == NULL)
return;
if (strcmp(a, b))
if (strcmp_P(a, b))
{
printf("string.c:%d (%s)\n", l, it);
printf(PSTR("string.c:%d (%s)\n"), l, it);
}
}
@ -57,7 +136,7 @@ static char two[50];
void libm_test_string()
{
/* Test strcmp first because we use it to test other things. */
it = "strcmp";
it = PSTR("strcmp");
check(strcmp("", "") == 0); /* Trivial case. */
check(strcmp("a", "a") == 0); /* Identity. */
check(strcmp("abc", "abc") == 0); /* Multicharacter. */
@ -69,7 +148,7 @@ void libm_test_string()
check(strcmp("a\103", "a\003") > 0);
/* Test strcpy next because we need it to set up other tests. */
it = "strcpy";
it = PSTR("strcpy");
check(strcpy(one, "abcd") == one); /* Returned value. */
equal(one, "abcd"); /* Basic test. */
@ -78,7 +157,7 @@ void libm_test_string()
equal(one + 2, "cd"); /* Wrote too much? */
(void)strcpy(two, "hi there");
(void)strcpy(one, two);
(void)xstrcpy(one, two);
equal(one, "hi there"); /* Basic test encore. */
equal(two, "hi there"); /* Stomped on source? */
@ -86,7 +165,7 @@ void libm_test_string()
equal(one, ""); /* Boundary condition. */
/* strcat. */
it = "strcat";
it = PSTR("strcat");
(void)strcpy(one, "ijk");
check(strcat(one, "lmn") == one); /* Returned value. */
equal(one, "ijklmn"); /* Basic test. */
@ -98,7 +177,7 @@ void libm_test_string()
(void)strcpy(one, "gh");
(void)strcpy(two, "ef");
(void)strcat(one, two);
(void)xstrcpy(one, two);
equal(one, "ghef"); /* Basic test encore. */
equal(two, "ef"); /* Stomped on source? */
@ -114,42 +193,67 @@ void libm_test_string()
/* strncat - first test it as strcat, with big counts,
then test the count mechanism. */
it = "strncat";
it = PSTR("strncat");
(void)strcpy(one, "ijk");
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow="
check(strncat(one, "lmn", 99) == one); /* Returned value. */
#pragma GCC diagnostic pop
equal(one, "ijklmn"); /* Basic test. */
(void)strcpy(one, "x");
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow="
(void)strncat(one, "yz", 99);
#pragma GCC diagnostic pop
equal(one, "xyz"); /* Writeover. */
equal(one + 4, "mn"); /* Wrote too much? */
(void)strcpy(one, "gh");
(void)strcpy(two, "ef");
(void)strncat(one, two, 99);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds="
#pragma GCC diagnostic ignored "-Wstringop-overflow="
(void)xstrncat(one, two, 99);
#pragma GCC diagnostic pop
equal(one, "ghef"); /* Basic test encore. */
equal(two, "ef"); /* Stomped on source? */
(void)strcpy(one, "");
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow="
(void)strncat(one, "", 99);
#pragma GCC diagnostic pop
equal(one, ""); /* Boundary conditions. */
(void)strcpy(one, "ab");
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow="
(void)strncat(one, "", 99);
#pragma GCC diagnostic pop
equal(one, "ab");
(void)strcpy(one, "");
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow="
(void)strncat(one, "cd", 99);
#pragma GCC diagnostic pop
equal(one, "cd");
(void)strcpy(one, "ab");
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-truncation"
(void)strncat(one, "cdef", 2);
#pragma GCC diagnostic pop
equal(one, "abcd"); /* Count-limited. */
(void)strncat(one, "gh", 0);
equal(one, "abcd"); /* Zero count. */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow"
(void)strncat(one, "gh", 2);
#pragma GCC diagnostic pop
equal(one, "abcdgh"); /* Count _AND length equal. */
it = "strncmp";
it = PSTR("strncmp");
/* strncmp - first test as strcmp with big counts";*/
check(strncmp("", "", 99) == 0); /* Trivial case. */
check(strncmp("a", "a", 99) == 0); /* Identity. */
@ -164,16 +268,22 @@ void libm_test_string()
check(strncmp("abc", "def", 0) == 0); /* Zero count. */
/* strncpy - testing is a bit different because of odd semantics. */
it = "strncpy";
it = PSTR("strncpy");
check(strncpy(one, "abc", 4) == one); /* Returned value. */
equal(one, "abc"); /* Did the copy go right? */
(void)strcpy(one, "abcdefgh");
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-truncation"
(void)strncpy(one, "xyz", 2);
#pragma GCC diagnostic pop
equal(one, "xycdefgh"); /* Copy cut by count. */
(void)strcpy(one, "abcdefgh");
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-truncation"
(void)strncpy(one, "xyz", 3); /* Copy cut just before NUL. */
#pragma GCC diagnostic pop
equal(one, "xyzdefgh");
(void)strcpy(one, "abcdefgh");
@ -188,7 +298,10 @@ void libm_test_string()
equal(one + 5, "fgh");
(void)strcpy(one, "abc");
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-truncation"
(void)strncpy(one, "xyz", 0); /* Zero-length copy. */
#pragma GCC diagnostic pop
equal(one, "abc");
(void)strncpy(one, "", 2); /* Zero-length source. */
@ -197,18 +310,18 @@ void libm_test_string()
equal(one + 2, "c");
(void)strcpy(one, "hi there");
(void)strncpy(two, one, 9);
(void)xstrncpy(two, one, 9);
equal(two, "hi there"); /* Just paranoia. */
equal(one, "hi there"); /* Stomped on source? */
/* strlen. */
it = "strlen";
it = PSTR("strlen");
check(strlen("") == 0); /* Empty. */
check(strlen("a") == 1); /* Single char. */
check(strlen("abcd") == 4); /* Multiple chars. */
/* strchr. */
it = "strchr";
it = PSTR("strchr");
check(strchr("abcd", 'z') == NULL); /* Not found. */
(void)strcpy(one, "abcd");
check(strchr(one, 'c') == one + 2); /* Basic test. */
@ -222,7 +335,7 @@ void libm_test_string()
check(strchr(one, '\0') == one); /* NUL in empty string. */
/* index - just like strchr. */
it = "index";
it = PSTR("index");
check(index("abcd", 'z') == NULL); /* Not found. */
(void)strcpy(one, "abcd");
check(index(one, 'c') == one + 2); /* Basic test. */
@ -236,7 +349,7 @@ void libm_test_string()
check(index(one, '\0') == one); /* NUL in empty string. */
/* strrchr. */
it = "strrchr";
it = PSTR("strrchr");
check(strrchr("abcd", 'z') == NULL); /* Not found. */
(void)strcpy(one, "abcd");
check(strrchr(one, 'c') == one + 2); /* Basic test. */
@ -250,7 +363,7 @@ void libm_test_string()
check(strrchr(one, '\0') == one); /* NUL in empty string. */
/* rindex - just like strrchr. */
it = "rindex";
it = PSTR("rindex");
check(rindex("abcd", 'z') == NULL); /* Not found. */
(void)strcpy(one, "abcd");
check(rindex(one, 'c') == one + 2); /* Basic test. */
@ -264,7 +377,7 @@ void libm_test_string()
check(rindex(one, '\0') == one); /* NUL in empty string. */
/* strpbrk - somewhat like strchr. */
it = "strpbrk";
it = PSTR("strpbrk");
check(strpbrk("abcd", "z") == NULL); /* Not found. */
(void)strcpy(one, "abcd");
check(strpbrk(one, "c") == one + 2); /* Basic test. */
@ -281,7 +394,7 @@ void libm_test_string()
check(strpbrk(one, "") == NULL); /* Both strings empty. */
/* strstr - somewhat like strchr. */
it = "strstr";
it = PSTR("strstr");
check(strstr("z", "abcd") == NULL); /* Not found. */
check(strstr("abx", "abcd") == NULL); /* Dead end. */
(void)strcpy(one, "abcd");
@ -304,7 +417,7 @@ void libm_test_string()
check(strstr(one, "bbca") == one + 1); /* With overlap. */
/* strspn. */
it = "strspn";
it = PSTR("strspn");
check(strspn("abcba", "abc") == 5); /* Whole string. */
check(strspn("abcba", "ab") == 2); /* Partial. */
check(strspn("abc", "qx") == 0); /* None. */
@ -312,7 +425,7 @@ void libm_test_string()
check(strspn("abc", "") == 0); /* Null search list. */
/* strcspn. */
it = "strcspn";
it = PSTR("strcspn");
check(strcspn("abcba", "qx") == 5); /* Whole string. */
check(strcspn("abcba", "cx") == 2); /* Partial. */
check(strcspn("abc", "abc") == 0); /* None. */
@ -320,7 +433,7 @@ void libm_test_string()
check(strcspn("abc", "") == 3); /* Null search list. */
/* strtok - the hard one. */
it = "strtok";
it = PSTR("strtok");
(void)strcpy(one, "first, second, third");
equal(strtok(one, ", "), "first"); /* Basic test. */
equal(one, "first");
@ -367,7 +480,7 @@ void libm_test_string()
equal(one + 4, "c");
/* memcmp. */
it = "memcmp";
it = PSTR("memcmp");
check(memcmp("a", "a", 1) == 0); /* Identity. */
check(memcmp("abc", "abc", 3) == 0); /* Multicharacter. */
check(memcmp("abcd", "abce", 4) < 0); /* Honestly unequal. */
@ -379,25 +492,25 @@ void libm_test_string()
/* memcmp should test strings as unsigned */
one[0] = 0xfe;
two[0] = 0x03;
check(memcmp(one, two, 1) > 0);
check(xmemcmp(one, two, 1) > 0);
/* memchr. */
it = "memchr";
it = PSTR("memchr");
check(memchr("abcd", 'z', 4) == NULL); /* Not found. */
(void)strcpy(one, "abcd");
check(memchr(one, 'c', 4) == one + 2); /* Basic test. */
check(memchr(one, 'd', 4) == one + 3); /* End of string. */
check(memchr(one, 'a', 4) == one); /* Beginning. */
check(memchr(one, '\0', 5) == one + 4); /* Finding NUL. */
check(xmemchr(one, 'c', 4) == one + 2); /* Basic test. */
check(xmemchr(one, 'd', 4) == one + 3); /* End of string. */
check(xmemchr(one, 'a', 4) == one); /* Beginning. */
check(xmemchr(one, '\0', 5) == one + 4); /* Finding NUL. */
(void)strcpy(one, "ababa");
check(memchr(one, 'b', 5) == one + 1); /* Finding first. */
check(memchr(one, 'b', 0) == NULL); /* Zero count. */
check(memchr(one, 'a', 1) == one); /* Singleton case. */
check(xmemchr(one, 'b', 5) == one + 1); /* Finding first. */
check(xmemchr(one, 'b', 0) == NULL); /* Zero count. */
check(xmemchr(one, 'a', 1) == one); /* Singleton case. */
(void)strcpy(one, "a\203b");
check(memchr(one, 0203, 3) == one + 1); /* Unsignedness. */
check(xmemchr(one, 0203, 3) == one + 1); /* Unsignedness. */
/* memcpy - need not work for overlap. */
it = "memcpy";
it = PSTR("memcpy");
check(memcpy(one, "abc", 4) == one); /* Returned value. */
equal(one, "abc"); /* Did the copy go right? */
@ -411,13 +524,13 @@ void libm_test_string()
(void)strcpy(one, "hi there");
(void)strcpy(two, "foo");
(void)memcpy(two, one, 9);
(void)xmemcpy(two, one, 9);
equal(two, "hi there"); /* Just paranoia. */
equal(one, "hi there"); /* Stomped on source? */
#if 0
#if 1
/* memmove - must work on overlap. */
it = "memmove";
check(memmove(one, "abc", 4) == one); /* Returned value. */
it = PSTR("memmove");
check(xmemmove(one, "abc", 4) == one); /* Returned value. */
equal(one, "abc"); /* Did the copy go right? */
(void) strcpy(one, "abcdefgh");
@ -430,20 +543,20 @@ void libm_test_string()
(void) strcpy(one, "hi there");
(void) strcpy(two, "foo");
(void) memmove(two, one, 9);
(void) xmemmove(two, one, 9);
equal(two, "hi there"); /* Just paranoia. */
equal(one, "hi there"); /* Stomped on source? */
(void) strcpy(one, "abcdefgh");
(void) memmove(one+1, one, 9);
(void) xmemmove(one+1, one, 9);
equal(one, "aabcdefgh"); /* Overlap, right-to-left. */
(void) strcpy(one, "abcdefgh");
(void) memmove(one+1, one+2, 7);
(void) xmemmove(one+1, one+2, 7);
equal(one, "acdefgh"); /* Overlap, left-to-right. */
(void) strcpy(one, "abcdefgh");
(void) memmove(one, one, 9);
(void) xmemmove(one, one, 9);
equal(one, "abcdefgh"); /* 100% overlap. */
#endif
#if 0
@ -451,7 +564,7 @@ void libm_test_string()
The SVID, the only place where memccpy is mentioned, says
overlap might fail, so we don't try it. Besides, it's hard
to see the rationale for a non-left-to-right memccpy. */
it = "memccpy";
it = PSTR("memccpy");
check(memccpy(one, "abc", 'q', 4) == NULL); /* Returned value. */
equal(one, "abc"); /* Did the copy go right? */
@ -486,12 +599,15 @@ void libm_test_string()
equal(two, "xbcdlebee");
#endif
/* memset. */
it = "memset";
it = PSTR("memset");
(void)strcpy(one, "abcdefgh");
check(memset(one + 1, 'x', 3) == one + 1); /* Return value. */
equal(one, "axxxefgh"); /* Basic test. */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmemset-transposed-args"
(void)memset(one + 2, 'y', 0);
#pragma GCC diagnostic pop
equal(one, "axxxefgh"); /* Zero-length set. */
(void)memset(one + 5, 0, 1);
@ -503,7 +619,7 @@ void libm_test_string()
/* bcopy - much like memcpy.
Berklix manual is silent about overlap, so don't test it. */
it = "bcopy";
it = PSTR("bcopy");
(void)bcopy("abc", one, 4);
equal(one, "abc"); /* Simple copy. */
@ -522,7 +638,7 @@ void libm_test_string()
equal(one, "hi there"); /* Stomped on source? */
/* bzero. */
it = "bzero";
it = PSTR("bzero");
(void)strcpy(one, "abcdef");
bzero(one + 2, 2);
equal(one, "ab"); /* Basic test. */
@ -534,7 +650,7 @@ void libm_test_string()
equal(one, "abcdef"); /* Zero-length copy. */
/* bcmp - somewhat like memcmp. */
it = "bcmp";
it = PSTR("bcmp");
check(bcmp("a", "a", 1) == 0); /* Identity. */
check(bcmp("abc", "abc", 3) == 0); /* Multicharacter. */
check(bcmp("abcd", "abce", 4) != 0); /* Honestly unequal. */

View File

@ -62,6 +62,7 @@ int errors = 0;
printf
/* A safe target-independent memmove. */
void mymemmove(unsigned char* dest, unsigned char* src, size_t n) __attribute__((__noinline__));
void mymemmove(unsigned char* dest, unsigned char* src, size_t n)
{

View File

@ -31,18 +31,8 @@
#include <stdio.h>
#include <stdarg.h>
#define memcmp memcmp_P
#define memcpy memcpy_P
#define memmem memmem_P
#define memchr memchr_P
#define strcat strcat_P
#define strncat strncat_P
#define strcpy strcpy_P
#define strncpy strncpy_P
#define strlen strlen_P
#define strnlen strnlen_P
#define strcmp strcmp_P
#define strncmp strncmp_P
#define BUFF_SIZE 256

View File

@ -0,0 +1,4 @@
/*@create-file:build.opt@
-fno-builtin
*/

View File

@ -13,6 +13,7 @@
#define MAX_1 50
#define memcmp memcmp_P
#define memcpy memcpy_P
#define memmove memmove_P
#define memmem memmem_P
#define memchr memchr_P
#define strcat strcat_P
@ -86,6 +87,8 @@ void tstring_main(void)
tmp2[0] = 'Z';
tmp2[1] = '\0';
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmemset-transposed-args"
if (memset(target, 'X', 0) != target || memcpy(target, "Y", 0) != target
|| memmove(target, "K", 0) != target || strncpy(tmp2, "4", 0) != tmp2
|| strncat(tmp2, "123", 0) != tmp2 || strcat(target, "") != target)
@ -93,6 +96,7 @@ void tstring_main(void)
eprintf(__LINE__, target, "A", 0);
test_failed = 1;
}
#pragma GCC diagnostic pop
if (strcmp(target, "A") || strlen(target) != 1 || memchr(target, 'A', 0) != NULL
|| memcmp(target, "J", 0) || strncmp(target, "A", 1) || strncmp(target, "J", 0)

View File

@ -1,5 +1,5 @@
#include <ESP8266WiFi.h>
#include "FS.h"
#include <LittleFS.h>
#include <BSTest.h>
BS_ENV_DECLARE();
@ -18,17 +18,17 @@ bool pretest()
TEST_CASE("read-write test","[fs]")
{
REQUIRE(SPIFFS.begin());
REQUIRE(LittleFS.begin());
String text = "write test";
{
File out = SPIFFS.open("/tmp.txt", "w");
File out = LittleFS.open("/tmp.txt", "w");
REQUIRE(out);
out.print(text);
}
{
File in = SPIFFS.open("/tmp.txt", "r");
File in = LittleFS.open("/tmp.txt", "r");
REQUIRE(in);
CHECK(in.size() == text.length());
in.setTimeout(0);
@ -39,14 +39,14 @@ TEST_CASE("read-write test","[fs]")
TEST_CASE("A bunch of files show up in openDir, and can be removed", "[fs]")
{
REQUIRE(SPIFFS.begin());
REQUIRE(LittleFS.begin());
const int n = 10;
int found[n] = {0};
{
Dir root = SPIFFS.openDir("");
Dir root = LittleFS.openDir("");
while (root.next()) {
CHECK(SPIFFS.remove(root.fileName()));
CHECK(LittleFS.remove(root.fileName()));
}
}
@ -55,14 +55,14 @@ TEST_CASE("A bunch of files show up in openDir, and can be removed", "[fs]")
name += i;
name += ".txt";
File out = SPIFFS.open(name, "w");
File out = LittleFS.open(name, "w");
REQUIRE(out);
out.println(i);
}
{
Dir root = SPIFFS.openDir("/");
Dir root = LittleFS.openDir("/");
while (root.next()) {
String fileName = root.fileName();
CHECK(fileName.indexOf("/seq_") == 0);
@ -77,35 +77,35 @@ TEST_CASE("A bunch of files show up in openDir, and can be removed", "[fs]")
}
{
Dir root = SPIFFS.openDir("/");
Dir root = LittleFS.openDir("/");
while (root.next()) {
String fileName = root.fileName();
CHECK(SPIFFS.remove(fileName));
CHECK(LittleFS.remove(fileName));
}
}
}
TEST_CASE("files can be renamed", "[fs]")
{
REQUIRE(SPIFFS.begin());
REQUIRE(LittleFS.begin());
{
File tmp = SPIFFS.open("/tmp1.txt", "w");
File tmp = LittleFS.open("/tmp1.txt", "w");
tmp.println("rename test");
}
{
CHECK(SPIFFS.rename("/tmp1.txt", "/tmp2.txt"));
CHECK(LittleFS.rename("/tmp1.txt", "/tmp2.txt"));
File tmp2 = SPIFFS.open("/tmp2.txt", "r");
File tmp2 = LittleFS.open("/tmp2.txt", "r");
CHECK(tmp2);
}
}
TEST_CASE("FS::info works","[fs]")
{
REQUIRE(SPIFFS.begin());
REQUIRE(LittleFS.begin());
FSInfo info;
CHECK(SPIFFS.info(info));
CHECK(LittleFS.info(info));
Serial.printf("Total: %u\nUsed: %u\nBlock: %u\nPage: %u\nMax open files: %u\nMax path len: %u\n",
info.totalBytes,
@ -119,10 +119,10 @@ TEST_CASE("FS::info works","[fs]")
TEST_CASE("FS is empty after format","[fs]")
{
REQUIRE(SPIFFS.begin());
REQUIRE(SPIFFS.format());
REQUIRE(LittleFS.begin());
REQUIRE(LittleFS.format());
Dir root = SPIFFS.openDir("/");
Dir root = LittleFS.openDir("/");
int count = 0;
while (root.next()) {
++count;
@ -132,12 +132,12 @@ TEST_CASE("FS is empty after format","[fs]")
TEST_CASE("Can reopen empty file","[fs]")
{
REQUIRE(SPIFFS.begin());
REQUIRE(LittleFS.begin());
{
File tmp = SPIFFS.open("/tmp.txt", "w");
File tmp = LittleFS.open("/tmp.txt", "w");
}
{
File tmp = SPIFFS.open("/tmp.txt", "w");
File tmp = LittleFS.open("/tmp.txt", "w");
CHECK(tmp);
}
}

View File

@ -85,6 +85,7 @@ def find_core_files():
)
if file.is_file()
and file.suffix in (".c", ".cpp", ".h", ".hpp")
and not GIT_ROOT / "tests/device/test_libc" in file.parents
and not GIT_ROOT / "tests/host/bin" in file.parents
and not GIT_ROOT / "tests/host/common/catch.hpp" == file
]