This commit is contained in:
Matthew Kennedy 2022-07-20 15:12:39 -07:00
parent d5f5870a02
commit f58f39c520
8 changed files with 526 additions and 0 deletions

57
.github/workflows/tests.yaml vendored Normal file
View File

@ -0,0 +1,57 @@
name: Unit Tests
on: [push,pull_request]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-20.04, macos-latest]
steps:
- uses: actions/checkout@v1
with:
submodules: recursive
fetch-depth: 0
- name: Discover cores
if: ${{ matrix.os != 'macos-latest' }}
run: lscpu | egrep 'Model name|Socket|Thread|NUMA|CPU\(s\)'
- name: Install required software (ubuntu)
if: ${{ matrix.os != 'macos-latest' }}
run: |
sudo apt-get update
sudo apt-get install valgrind
- name: Print Compiler version
# NOTE: on mac, this is actually symlink'd to clang, not gcc, but that's ok - we want to build on both
working-directory: .
run: gcc -v
- name: Build Tests
working-directory: ./unit_tests/
run: make -j4 SANITIZE=yes
- name: Run Tests
working-directory: ./unit_tests/
run: ASAN_OPTIONS=detect_stack_use_after_return=1 build/libfirmware_test
- name: Run Tests (sharded)
working-directory: ./unit_tests/
run: bash ./run_sharded_tests.sh
- name: Rebuild Tests For Valgrind
# Valgrind isn't compatible with address sanitizer, so we have to rebuild the code
if: ${{ matrix.os != 'macos-latest' }}
working-directory: ./unit_tests/
run: |
make clean
make -j4 SANITIZE=no
- name: Run Tests (Valgrind)
if: ${{ matrix.os != 'macos-latest' }}
working-directory: ./unit_tests/
run: valgrind --error-exitcode=1 --leak-check=no build/libfirmware_test

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "ext/googletest"]
path = ext/googletest
url = https://github.com/google/googletest.git

28
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,28 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Debug Unit Tests (gdb)",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/libfirmware_test",
// uncomment args below to only debug a particular test
//"args": ["--gtest_filter=Util_CRC.crc8"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}

200
Makefile Normal file
View File

@ -0,0 +1,200 @@
##############################################################################
# Build global options
# NOTE: Can be overridden externally.
#
PROJECT_DIR = .
# Imported source files and paths
RUSEFI_LIB = .
include $(RUSEFI_LIB)/util/util.mk
# C sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CSRC +=
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CPPSRC += \
$(RUSEFI_LIB_CPP) \
$(RUSEFI_LIB_CPP_TEST) \
gtest-all.cpp \
gmock-all.cpp \
gtest_main.cpp \
INCDIR += \
$(PROJECT_DIR)/ext/googletest/googlemock/ \
$(PROJECT_DIR)/ext/googletest/googlemock/include \
$(PROJECT_DIR)/ext/googletest/googletest \
$(PROJECT_DIR)/ext/googletest/googletest/include \
$(RUSEFI_LIB_INC) \
SANITIZE = yes
IS_MAC = no
ifneq ($(OS),Windows_NT)
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
IS_MAC = yes
endif
endif
# Compiler options here.
ifeq ($(USE_OPT),)
# -O2 is needed for mingw, without it there is a linking issue to isnanf?!?!
#USE_OPT = $(RFLAGS) -O2 -fgnu89-inline -ggdb -fomit-frame-pointer -falign-functions=16 -std=gnu99 -Werror-implicit-function-declaration -Werror -Wno-error=pointer-sign -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=sign-compare -Wno-error=unused-parameter -Wno-error=missing-field-initializers
USE_OPT = -c -Wall -O0 -ggdb -g
USE_OPT += -Werror=missing-field-initializers -Wno-error=sign-compare
endif
ifeq ($(COVERAGE),yes)
USE_OPT += -fprofile-arcs -ftest-coverage
endif
# See explanation in main firmware Makefile for these three defines
USE_OPT += -DEFI_UNIT_TEST=1 -DEFI_PROD_CODE=0 -DEFI_SIMULATOR=0
# Pretend we are all different hardware so that all canned engine configs are included
USE_OPT += -DHW_MICRO_RUSEFI=1 -DHW_PROTEUS=1 -DHW_FRANKENSO=1 -DHW_HELLEN=1
# C specific options here (added to USE_OPT).
ifeq ($(USE_COPT),)
USE_COPT = -std=gnu99 -fgnu89-inline
endif
# C++ specific options here (added to USE_OPT).
ifeq ($(USE_CPPOPT),)
USE_CPPOPT = -std=gnu++2a -fno-rtti -fno-use-cxa-atexit
endif
# Enable address sanitizer for C++ files, but not on Windows since x86_64-w64-mingw32-g++ doesn't support it.
# only c++ because lua does some things asan doesn't like, but don't actually cause overruns.
ifeq ($(SANITIZE),yes)
ifeq ($(IS_MAC),yes)
USE_CPPOPT += -fsanitize=address
else
USE_CPPOPT += -fsanitize=address -fsanitize=bounds-strict -fno-sanitize-recover=all
endif
endif
# Enable this if you want the linker to remove unused code and data
ifeq ($(USE_LINK_GC),)
USE_LINK_GC = yes
endif
# Enable this if you want to see the full log while compiling.
ifeq ($(USE_VERBOSE_COMPILE),)
USE_VERBOSE_COMPILE = no
endif
# C sources to be compiled in ARM mode regardless of the global setting.
ACSRC =
# C++ sources to be compiled in ARM mode regardless of the global setting.
ACPPSRC =
# List ASM source files here
ASMSRC =
##############################################################################
# Compiler settings
#
# It looks like cygwin build of mingwg-w64 has issues with gcov runtime :(
# mingw-w64 is a project which forked from mingw in 2007 - be careful not to confuse these two.
# In order to have coverage generated please download from https://mingw-w64.org/doku.php/download/mingw-builds
# Install using mingw-w64-install.exe instead of similar thing packaged with cygwin
# Both 32 bit and 64 bit versions of mingw-w64 are generating coverage data.
ifeq ($(OS),Windows_NT)
ifeq ($(USE_MINGW32_I686),)
#this one is 64 bit
TRGT = x86_64-w64-mingw32-
else
#this one was 32 bit
TRGT = i686-w64-mingw32-
endif
else
TRGT =
endif
CC = $(TRGT)gcc
CPPC = $(TRGT)g++
LD = $(TRGT)g++
CP = $(TRGT)objcopy
AS = $(TRGT)gcc -x assembler-with-cpp
OD = $(TRGT)objdump
HEX = $(CP) -O ihex
BIN = $(CP) -O binary
# Define C warning options here
CWARN = -Wall -Wextra -Wstrict-prototypes -pedantic -Wmissing-prototypes -Wold-style-definition
# Define C++ warning options here
CPPWARN = -Wall -Wextra -Werror -pedantic
#
# Compiler settings
##############################################################################
##############################################################################
# Start of default section
#
# List all default ASM defines here, like -D_DEBUG=1
DADEFS =
# List all default directories to look for include files here
DINCDIR =
# List the default directory to look for the libraries here
DLIBDIR =
# List all default libraries here
ifeq ($(OS),Windows_NT)
# Windows
DLIBS = -static-libgcc -static -static-libstdc++
else
# Linux
DLIBS = -pthread
endif
#
# End of default section
##############################################################################
##############################################################################
# Start of user section
#
# List all user C define here, like -D_DEBUG=1
UDEFS =
# Define ASM defines here
UADEFS =
# List all user directories here
UINCDIR =
# List the user directory to look for the libraries here
ULIBDIR =
# List all user libraries here
ULIBS = -lm
ifeq ($(COVERAGE),yes)
ULIBS += --coverage
endif
ifeq ($(SANITIZE),yes)
ULIBS += -fsanitize=address -fsanitize=undefined
endif
#
# End of user defines
##############################################################################
# Define project name here
PROJECT = libfirmware_test
include rules.mk

13
gmock-all.cpp Normal file
View File

@ -0,0 +1,13 @@
// this is a work-around since our Makefile does not recognice .cc format
// todo: adjust the makefile so that we can remove this
// This line ensures that gmock.h can be compiled on its own, even
// when it's fused.
#include "gmock/gmock.h"
// The following lines pull in the real gmock *.cc files.
#include "src/gmock-cardinalities.cc"
#include "src/gmock-internal-utils.cc"
#include "src/gmock-matchers.cc"
#include "src/gmock-spec-builders.cc"
#include "src/gmock.cc"

17
gtest-all.cpp Normal file
View File

@ -0,0 +1,17 @@
// this is a work-around since our Makefile does not recognice .cc format
// todo: adjust the makefile so that we can remove this
// This line ensures that gtest.h can be compiled on its own, even
// when it's fused.
#include "gtest/gtest.h"
// The following lines pull in the real gtest *.cc files.
#include "src/gtest-assertion-result.cc"
#include "src/gtest-death-test.cc"
#include "src/gtest-filepath.cc"
#include "src/gtest-matchers.cc"
#include "src/gtest-port.cc"
#include "src/gtest-printers.cc"
#include "src/gtest-test-part.cc"
#include "src/gtest-typed-test.cc"
#include "src/gtest.cc"

53
gtest_main.cpp Normal file
View File

@ -0,0 +1,53 @@
// Copyright 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * 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.
// * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT
// OWNER 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.
#include <cstdio>
#include "gtest/gtest.h"
#if GTEST_OS_ESP8266 || GTEST_OS_ESP32
#if GTEST_OS_ESP8266
extern "C" {
#endif
void setup() { testing::InitGoogleTest(); }
void loop() { RUN_ALL_TESTS(); }
#if GTEST_OS_ESP8266
}
#endif
#else
GTEST_API_ int main(int argc, char **argv) {
printf("Running main() from %s\n", __FILE__);
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
#endif

155
rules.mk Normal file
View File

@ -0,0 +1,155 @@
# ARM Cortex-Mx common makefile scripts and rules.
ifeq ($(BUILDDIR),)
# Define if not specified
BUILDDIR = build
endif
ifeq ($(BUILDDIR),.)
# Redefine if pointing at current folder
BUILDDIR = build
endif
BINARY_OUTPUT = $(BUILDDIR)/$(PROJECT)
# Automatic compiler options
OPT = $(USE_OPT)
COPT = $(USE_COPT)
CPPOPT = $(USE_CPPOPT)
ifeq ($(USE_LINK_GC),yes)
OPT += -ffunction-sections -fdata-sections -fno-common
endif
ACSRC += $(CSRC)
ACPPSRC += $(CPPSRC)
ASRC = $(ACSRC)$(ACPPSRC)
SRCPATHS = $(sort $(dir $(ASMXSRC)) $(dir $(ASMSRC)) $(dir $(ASRC)))
# Various directories
OBJDIR = $(BUILDDIR)/obj
LSTDIR = $(BUILDDIR)/lst
# Object files groups
ACOBJS = $(addprefix $(OBJDIR)/, $(notdir $(ACSRC:.c=.o)))
ACPPOBJS = $(addprefix $(OBJDIR)/, $(notdir $(ACPPSRC:.cpp=.o)))
ASMOBJS = $(addprefix $(OBJDIR)/, $(notdir $(ASMSRC:.s=.o)))
ASMXOBJS = $(addprefix $(OBJDIR)/, $(notdir $(ASMXSRC:.S=.o)))
OBJS = $(ASMXOBJS) $(ASMOBJS) $(ACOBJS) $(ACPPOBJS)
# Paths
IINCDIR = $(patsubst %,-I%,$(INCDIR) $(DINCDIR) $(UINCDIR))
LLIBDIR = $(patsubst %,-L%,$(DLIBDIR) $(ULIBDIR))
# Macros
DEFS = $(DDEFS) $(UDEFS)
ADEFS = $(DADEFS) $(UADEFS)
# Libs
LIBS = $(DLIBS) $(ULIBS)
# Various settings
ifeq ($(IS_MAC),yes)
ODFLAGS = -x --syms
ASFLAGS = $(MCFLAGS) -Wa $(ADEFS)
ASXFLAGS = $(MCFLAGS) -Wa $(ADEFS)
CFLAGS = $(MCFLAGS) $(OPT) $(COPT) $(CWARN) $(DEFS)
CPPFLAGS = $(MCFLAGS) $(OPT) $(CPPOPT) $(CPPWARN) $(DEFS)
LDFLAGS = $(MCFLAGS) $(LLIBDIR)
else
# not mac
ODFLAGS = -x --syms
ASFLAGS = $(MCFLAGS) $(ADEFS)
ASXFLAGS = $(MCFLAGS) $(ADEFS)
CFLAGS = $(MCFLAGS) $(OPT) $(COPT) $(CWARN) $(DEFS)
CPPFLAGS = $(MCFLAGS) $(OPT) $(CPPOPT) $(CPPWARN) $(DEFS)
ifeq ($(USE_LINK_GC),yes)
LDFLAGS = $(MCFLAGS) -Wl,-Map=$(BINARY_OUTPUT).map,--cref,--no-warn-mismatch,--gc-sections $(LLIBDIR)
else
LDFLAGS = $(MCFLAGS) -Wl,-Map=$(BINARY_OUTPUT).map,--cref,--no-warn-mismatch $(LLIBDIR)
endif
endif
# Generate dependency information
CFLAGS += -MD -MP -MF .dep/$(@F).d
CPPFLAGS += -MD -MP -MF .dep/$(@F).d
# Paths where to search for sources
VPATH = $(SRCPATHS)
#
# Makefile rules
#
all: $(OBJS) $(BINARY_OUTPUT) MAKE_ALL_RULE_HOOK
MAKE_ALL_RULE_HOOK:
$(OBJS): | $(BUILDDIR)
$(BUILDDIR) $(OBJDIR) $(LSTDIR):
ifneq ($(USE_VERBOSE_COMPILE),yes)
@echo Compiler Options
@echo $(CPPC) -c $(CPPFLAGS) -I. $(IINCDIR) main.cpp -o main.o
@echo
endif
mkdir -p $(OBJDIR)
mkdir -p $(LSTDIR)
$(ACPPOBJS) : $(OBJDIR)/%.o : %.cpp Makefile
ifeq ($(USE_VERBOSE_COMPILE),yes)
@echo
$(CPPC) -c $(CPPFLAGS) $(AOPT) -I. $(IINCDIR) $< -o $@
else
@echo Compiling $(<F)
@$(CPPC) -c $(CPPFLAGS) $(AOPT) -I. $(IINCDIR) $< -o $@
endif
$(ACOBJS) : $(OBJDIR)/%.o : %.c Makefile
ifeq ($(USE_VERBOSE_COMPILE),yes)
@echo
$(CC) -c $(CFLAGS) $(AOPT) -I. $(IINCDIR) $< -o $@
else
@echo Compiling $(<F)
@$(CC) -c $(CFLAGS) $(AOPT) -I. $(IINCDIR) $< -o $@
endif
$(ASMOBJS) : $(OBJDIR)/%.o : %.s Makefile
ifeq ($(USE_VERBOSE_COMPILE),yes)
@echo
$(AS) -c $(ASFLAGS) -I. $(IINCDIR) $< -o $@
else
@echo Compiling $(<F)
@$(AS) -c $(ASFLAGS) -I. $(IINCDIR) $< -o $@
endif
$(ASMXOBJS) : $(OBJDIR)/%.o : %.S Makefile
ifeq ($(USE_VERBOSE_COMPILE),yes)
@echo
$(CC) -c $(ASXFLAGS) $(TOPT) -I. $(IINCDIR) $< -o $@
else
@echo Compiling $(<F)
@$(CC) -c $(ASXFLAGS) $(TOPT) -I. $(IINCDIR) $< -o $@
endif
$(BINARY_OUTPUT): $(OBJS)
rm -rf $(BUILDDIR)/obj/*gcda
ifeq ($(USE_VERBOSE_COMPILE),yes)
@echo
$(LD) $(OBJS) $(LDFLAGS) $(LIBS) -o $@
else
@echo Linking $@
@$(LD) $(OBJS) $(LDFLAGS) $(LIBS) -o $@
endif
clean: CLEAN_RULE_HOOK
@echo Cleaning
-rm -fR .dep $(BUILDDIR)
@echo Done
CLEAN_RULE_HOOK:
#
# Include the dependency files, should be the last of the makefile
#
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
# *** EOF ***