summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Humbert <jack.humb@gmail.com>2016-08-27 17:06:45 -0400
committerGitHub <noreply@github.com>2016-08-27 17:06:45 -0400
commit4fd5ac8326f491a347b8c049f32a3353a633ebf5 (patch)
treec82d8b5325ea82a7544489022afe00bf909495c3
parentf815b4871ebc5cc2f8d1a306eceec68c0a973a4c (diff)
parent922c4ea3bc46f6246d9f67ead11bcf53ff947ef3 (diff)
Merge pull request #690 from fredizzimo/unit_test
Add Unit Testing support
-rw-r--r--.gitmodules3
-rw-r--r--.travis.yml10
-rw-r--r--Makefile71
-rw-r--r--build_keyboard.mk52
-rw-r--r--build_test.mk57
-rw-r--r--common.mk26
m---------lib/googletest0
-rw-r--r--message.mk8
-rw-r--r--quantum/serial_link/protocol/byte_stuffer.c3
-rw-r--r--quantum/serial_link/protocol/byte_stuffer.h3
-rw-r--r--quantum/serial_link/protocol/transport.c4
-rw-r--r--quantum/serial_link/protocol/transport.h7
-rw-r--r--quantum/serial_link/tests/byte_stuffer_tests.cpp (renamed from quantum/serial_link/tests/byte_stuffer_tests.c)313
-rw-r--r--quantum/serial_link/tests/frame_router_tests.c231
-rw-r--r--quantum/serial_link/tests/frame_router_tests.cpp229
-rw-r--r--quantum/serial_link/tests/frame_validator_tests.cpp (renamed from quantum/serial_link/tests/frame_validator_tests.c)90
-rw-r--r--quantum/serial_link/tests/rules.mk22
-rw-r--r--quantum/serial_link/tests/testlist.mk6
-rw-r--r--quantum/serial_link/tests/transport_tests.c168
-rw-r--r--quantum/serial_link/tests/transport_tests.cpp188
-rw-r--r--quantum/serial_link/tests/triple_buffered_object_tests.cpp (renamed from quantum/serial_link/tests/triple_buffered_object_tests.c)52
-rw-r--r--readme.md51
-rw-r--r--testlist.mk13
-rw-r--r--tmk_core/common.mk71
-rw-r--r--tmk_core/native.mk24
-rw-r--r--tmk_core/rules.mk29
26 files changed, 1007 insertions, 724 deletions
diff --git a/.gitmodules b/.gitmodules
index 7e3c92d031..12b7cb918f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -7,3 +7,6 @@
[submodule "lib/ugfx"]
path = lib/ugfx
url = https://bitbucket.org/Tectu/ugfx
+[submodule "lib/googletest"]
+ path = lib/googletest
+ url = https://github.com/google/googletest
diff --git a/.travis.yml b/.travis.yml
index 138a2c5532..f4c918a5ed 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,7 +10,10 @@ env:
global:
- secure: vBTSL34BDPxDilKUuTXqU4CJ26Pv5hogD2nghatkxSQkI1/jbdnLj/DQdPUrMJFDIY6TK3AltsBx72MaMsLQ1JO/Ou24IeHINHXzUC1FlS9yQa48cpxnhX5kzXNyGs3oa0qaFbvnr7RgYRWtmD52n4bIZuSuW+xpBv05x2OCizdT2ZonH33nATaHGFasxROm4qYZ241VfzcUv766V6RVHgL4x9V08warugs+RENVkfzxxwhk3NmkrISabze0gSVJLHBPHxroZC6EUcf/ocobcuDrCwFqtEt90i7pNIAFUE7gZsN2uE75LmpzAWin21G7lLPcPL2k4FJVd8an1HiP2WmscJU6U89fOfMb2viObnKcCzebozBCmKGtHEuXZo9FcReOx49AnQSpmESJGs+q2dL/FApkTjQiyT4J6O5dJpoww0/r57Wx0cmmqjETKBb5rSgXM51Etk3wO09mvcPHsEwrT7qH8r9XWdyCDoEn7FCLX3/LYnf/D4SmZ633YPl5gv3v9XEwxR5+04akjgnvWDSNIaDbWBdxHNb7l4pMc+WR1bwCyMyA7KXj0RrftEGOrm9ZRLe6BkbT4cycA+j77nbPOMcyZChliV9pPQos+4TOJoTzcK2L8yWVoY409aDNVuAjdP6Yum0R2maBGl/etLmIMpJC35C5/lZ+dUNjJAM=
script:
-- make all-keyboards AUTOGEN=true
+- make $TARGET AUTOGEN=$AUTOGEN
+env:
+- TARGET=all-keyboards AUTOGEN=true
+- TARGET=test AUTOGEN=false
addons:
apt:
packages:
@@ -22,4 +25,7 @@ addons:
- binutils-arm-none-eabi
- libnewlib-arm-none-eabi
- diffutils
-after_success: bash util/travis_compiled_push.sh
+after_success:
+ if [ "$AUTOGEN" == "true" ]; then
+ bash util/travis_compiled_push.sh;
+ fi
diff --git a/Makefile b/Makefile
index f78cca6c6f..0aaf585786 100644
--- a/Makefile
+++ b/Makefile
@@ -2,6 +2,10 @@ ifndef VERBOSE
.SILENT:
endif
+# Never run this makefile in parallel, as it could screw things up
+# It won't affect the submakes, so you still get the speedup from specifying -jx
+.NOTPARALLEL:
+
# Allow the silent with lower caps to work the same way as upper caps
ifdef silent
SILENT = $(silent)
@@ -28,6 +32,7 @@ ABS_ROOT_MAKEFILE := $(abspath $(ROOT_MAKEFILE))
ABS_STARTING_DIR := $(dir $(ABS_STARTING_MAKEFILE))
ABS_ROOT_DIR := $(dir $(ABS_ROOT_MAKEFILE))
STARTING_DIR := $(subst $(ABS_ROOT_DIR),,$(ABS_STARTING_DIR))
+TEST_DIR := $(ROOT_DIR)/.build/test
MAKEFILE_INCLUDED=yes
@@ -224,6 +229,8 @@ define PARSE_RULE
# PARSE_ALL_KEYBOARDS
ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,allkb),true)
$$(eval $$(call PARSE_ALL_KEYBOARDS))
+ else ifeq ($$(call COMPARE_AND_REMOVE_FROM_RULE,test),true)
+ $$(eval $$(call PARSE_TEST))
# If the rule starts with the name of a known keyboard, then continue
# the parsing from PARSE_KEYBOARD
else ifeq ($$(call TRY_TO_MATCH_RULE_FROM_LIST,$$(KEYBOARDS)),true)
@@ -356,7 +363,6 @@ define PARSE_KEYMAP
MAKE_TARGET := $$(patsubst -%,%,$$(RULE))
# We need to generate an unique indentifer to append to the COMMANDS list
COMMAND := COMMAND_KEYBOARD_$$(CURRENT_KB)_SUBPROJECT_$(CURRENT_SP)_KEYMAP_$$(CURRENT_KM)
- COMMANDS += $$(COMMAND)
# If we are compiling a keyboard without a subproject, we want to display just the name
# of the keyboard, otherwise keyboard/subproject
ifeq ($$(CURRENT_SP),)
@@ -368,13 +374,18 @@ define PARSE_KEYMAP
KB_SP := $(BOLD)$$(KB_SP)$(NO_COLOR)
# Specify the variables that we are passing forward to submake
MAKE_VARS := KEYBOARD=$$(CURRENT_KB) SUBPROJECT=$$(CURRENT_SP) KEYMAP=$$(CURRENT_KM)
- MAKE_VARS += VERBOSE=$(VERBOSE) COLOR=$(COLOR)
# And the first part of the make command
MAKE_CMD := $$(MAKE) -r -R -C $(ROOT_DIR) -f build_keyboard.mk $$(MAKE_TARGET)
# The message to display
MAKE_MSG := $$(MSG_MAKE_KB)
# We run the command differently, depending on if we want more output or not
# The true version for silent output and the false version otherwise
+ $$(eval $$(call BUILD))
+endef
+
+define BUILD
+ MAKE_VARS += VERBOSE=$(VERBOSE) COLOR=$(COLOR)
+ COMMANDS += $$(COMMAND)
COMMAND_true_$$(COMMAND) := \
printf "$$(MAKE_MSG)" | \
$$(MAKE_MSG_FORMAT); \
@@ -388,7 +399,10 @@ define PARSE_KEYMAP
fi;
COMMAND_false_$$(COMMAND) := \
printf "$$(MAKE_MSG)\n\n"; \
- $$(MAKE_CMD) $$(MAKE_VARS) SILENT=false;
+ $$(MAKE_CMD) $$(MAKE_VARS) SILENT=false; \
+ if [ $$$$? -gt 0 ]; \
+ then error_occured=1; \
+ fi;
endef
# Just parse all the keymaps for a specifc keyboard
@@ -396,6 +410,41 @@ define PARSE_ALL_KEYMAPS
$$(eval $$(call PARSE_ALL_IN_LIST,PARSE_KEYMAP,$$(KEYMAPS)))
endef
+define BUILD_TEST
+ TEST_NAME := $1
+ MAKE_TARGET := $2
+ COMMAND := $1
+ MAKE_CMD := $$(MAKE) -r -R -C $(ROOT_DIR) -f build_test.mk $$(MAKE_TARGET)
+ MAKE_VARS := TEST=$$(TEST_NAME)
+ MAKE_MSG := $$(MSG_MAKE_TEST)
+ $$(eval $$(call BUILD))
+ ifneq ($$(MAKE_TARGET),clean)
+ TEST_EXECUTABLE := $$(TEST_DIR)/$$(TEST_NAME).elf
+ TESTS += $$(TEST_NAME)
+ TEST_MSG := $$(MSG_TEST)
+ $$(TEST_NAME)_COMMAND := \
+ printf "$$(TEST_MSG)\n"; \
+ $$(TEST_EXECUTABLE); \
+ if [ $$$$? -gt 0 ]; \
+ then error_occured=1; \
+ fi; \
+ printf "\n";
+ endif
+endef
+
+define PARSE_TEST
+ TESTS :=
+ TEST_NAME := $$(firstword $$(subst -, ,$$(RULE)))
+ TEST_TARGET := $$(subst $$(TEST_NAME),,$$(subst $$(TEST_NAME)-,,$$(RULE)))
+ ifeq ($$(TEST_NAME),all)
+ MATCHED_TESTS := $$(TEST_LIST)
+ else
+ MATCHED_TESTS := $$(foreach TEST,$$(TEST_LIST),$$(if $$(findstring $$(TEST_NAME),$$(TEST)),$$(TEST),))
+ endif
+ $$(foreach TEST,$$(MATCHED_TESTS),$$(eval $$(call BUILD_TEST,$$(TEST),$$(TEST_TARGET))))
+endef
+
+
# Set the silent mode depending on if we are trying to compile multiple keyboards or not
# By default it's on in that case, but it can be overriden by specifying silent=false
# from the command line
@@ -440,12 +489,13 @@ $(SUBPROJECTS): %: %-allkm
# But we return the error code at the end, to trigger travis failures
+error_occured=0; \
$(foreach COMMAND,$(COMMANDS),$(RUN_COMMAND)) \
- if [ $$error_occured -gt 0 ]; then printf "$(MSG_ERRORS)" & exit $$error_occured; fi
-
+ if [ $$error_occured -gt 0 ]; then printf "$(MSG_ERRORS)" & exit $$error_occured; fi;\
+ $(foreach TEST,$(TESTS),$($(TEST)_COMMAND)) \
+ if [ $$error_occured -gt 0 ]; then printf "$(MSG_ERRORS)" & exit $$error_occured; fi;\
# All should compile everything
.PHONY: all
-all: all-keyboards
+all: all-keyboards test-all
# Define some shortcuts, mostly for compability with the old syntax
.PHONY: all-keyboards
@@ -454,9 +504,16 @@ all-keyboards: allkb-allsp-allkm
.PHONY: all-keyboards-defaults
all-keyboards-defaults: allkb-allsp-default
+.PHONY: test
+test: test-all
+
+.PHONY: test-clean
+test-clean: test-all-clean
# Generate the version.h file
GIT_VERSION := $(shell git describe --abbrev=6 --dirty --always --tags 2>/dev/null || date +"%Y-%m-%d-%H:%M:%S")
BUILD_DATE := $(shell date +"%Y-%m-%d-%H:%M:%S")
$(shell echo '#define QMK_VERSION "$(GIT_VERSION)"' > $(ROOT_DIR)/quantum/version.h)
-$(shell echo '#define QMK_BUILDDATE "$(BUILD_DATE)"' >> $(ROOT_DIR)/quantum/version.h) \ No newline at end of file
+$(shell echo '#define QMK_BUILDDATE "$(BUILD_DATE)"' >> $(ROOT_DIR)/quantum/version.h)
+
+include $(ROOT_DIR)/testlist.mk \ No newline at end of file
diff --git a/build_keyboard.mk b/build_keyboard.mk
index f843572f66..04632c1c94 100644
--- a/build_keyboard.mk
+++ b/build_keyboard.mk
@@ -4,19 +4,7 @@ endif
.DEFAULT_GOAL := all
-include message.mk
-
-
-# Directory common source filess exist
-TOP_DIR = .
-TMK_DIR = tmk_core
-TMK_PATH = $(TOP_DIR)/$(TMK_DIR)
-LIB_PATH = $(TOP_DIR)/lib
-
-QUANTUM_DIR = quantum
-QUANTUM_PATH = $(TOP_DIR)/$(QUANTUM_DIR)
-
-BUILD_DIR := $(TOP_DIR)/.build
+include common.mk
ifneq ($(SUBPROJECT),)
TARGET ?= $(KEYBOARD)_$(SUBPROJECT)_$(KEYMAP)
@@ -35,6 +23,16 @@ ifdef master
MASTER = $(master)
endif
+ifeq ($(MASTER),right)
+ OPT_DEFS += -DMASTER_IS_ON_RIGHT
+else
+ ifneq ($(MASTER),left)
+$(error MASTER does not have a valid value(left/right))
+ endif
+endif
+
+
+
KEYBOARD_PATH := keyboards/$(KEYBOARD)
KEYBOARD_C := $(KEYBOARD_PATH)/$(KEYBOARD).c
@@ -167,12 +165,8 @@ ifeq ($(strip $(TAP_DANCE_ENABLE)), yes)
endif
ifeq ($(strip $(SERIAL_LINK_ENABLE)), yes)
- SERIAL_DIR = $(QUANTUM_DIR)/serial_link
- SERIAL_PATH = $(QUANTUM_PATH)/serial_link
- SERIAL_SRC = $(wildcard $(SERIAL_PATH)/protocol/*.c)
- SERIAL_SRC += $(wildcard $(SERIAL_PATH)/system/*.c)
SRC += $(patsubst $(QUANTUM_PATH)/%,%,$(SERIAL_SRC))
- OPT_DEFS += -DSERIAL_LINK_ENABLE
+ OPT_DEFS += $(SERIAL_DEFS)
VAPTH += $(SERIAL_PATH)
endif
@@ -185,15 +179,14 @@ ifneq ($(SUBPROJECT),)
VPATH += $(SUBPROJECT_PATH)
endif
VPATH += $(KEYBOARD_PATH)
-VPATH += $(TOP_DIR)
-VPATH += $(TMK_PATH)
-VPATH += $(QUANTUM_PATH)
-VPATH += $(QUANTUM_PATH)/keymap_extras
-VPATH += $(QUANTUM_PATH)/audio
-VPATH += $(QUANTUM_PATH)/process_keycode
+VPATH += $(COMMON_VPATH)
include $(TMK_PATH)/common.mk
+SRC += $(TMK_COMMON_SRC)
+OPT_DEFS += $(TMK_COMMON_DEFS)
+EXTRALDFLAGS += $(TMK_COMMON_LDFLAGS)
+
ifeq ($(PLATFORM),AVR)
include $(TMK_PATH)/protocol/lufa.mk
include $(TMK_PATH)/avr.mk
@@ -205,17 +198,24 @@ ifeq ($(strip $(VISUALIZER_ENABLE)), yes)
include $(VISUALIZER_PATH)/visualizer.mk
endif
-
OUTPUTS := $(KEYMAP_OUTPUT) $(KEYBOARD_OUTPUT)
$(KEYMAP_OUTPUT)_SRC := $(SRC)
$(KEYMAP_OUTPUT)_DEFS := $(OPT_DEFS) -DQMK_KEYBOARD=\"$(KEYBOARD)\" -DQMK_KEYMAP=\"$(KEYMAP)\"
-$(KEYMAP_OUTPUT)_INC := $(EXTRAINCDIRS) $(VPATH)
+$(KEYMAP_OUTPUT)_INC := $(VPATH) $(EXTRAINCDIRS)
$(KEYMAP_OUTPUT)_CONFIG := $(CONFIG_H)
$(KEYBOARD_OUTPUT)_SRC := $(CHIBISRC)
$(KEYBOARD_OUTPUT)_DEFS := $(PROJECT_DEFS)
$(KEYBOARD_OUTPUT)_INC := $(PROJECT_INC)
$(KEYBOARD_OUTPUT)_CONFIG := $(PROJECT_CONFIG)
+# Default target.
+all: build sizeafter
+
+# Change the build target to build a HEX file or a library.
+build: elf hex
+#build: elf hex eep lss sym
+#build: lib
+
include $(TMK_PATH)/rules.mk
diff --git a/build_test.mk b/build_test.mk
new file mode 100644
index 0000000000..ee15a45726
--- /dev/null
+++ b/build_test.mk
@@ -0,0 +1,57 @@
+ifndef VERBOSE
+.SILENT:
+endif
+
+.DEFAULT_GOAL := all
+
+include common.mk
+
+TARGET=test/$(TEST)
+
+GTEST_OUTPUT = $(BUILD_DIR)/gtest
+
+TEST_OBJ = $(BUILD_DIR)/test_obj
+
+OUTPUTS := $(TEST_OBJ)/$(TEST) $(GTEST_OUTPUT)
+
+GTEST_INC := \
+ $(LIB_PATH)/googletest/googletest/include\
+ $(LIB_PATH)/googletest/googlemock/include\
+
+GTEST_INTERNAL_INC :=\
+ $(LIB_PATH)/googletest/googletest\
+ $(LIB_PATH)/googletest/googlemock
+
+$(GTEST_OUTPUT)_SRC :=\
+ googletest/src/gtest-all.cc\
+ googletest/src/gtest_main.cc\
+ googlemock/src/gmock-all.cc
+
+$(GTEST_OUTPUT)_DEFS :=
+$(GTEST_OUTPUT)_INC := $(GTEST_INC) $(GTEST_INTERNAL_INC)
+
+LDFLAGS += -lstdc++ -lpthread -shared-libgcc
+CREATE_MAP := no
+
+VPATH +=\
+ $(LIB_PATH)/googletest\
+ $(LIB_PATH)/googlemock
+
+all: elf
+
+VPATH += $(COMMON_VPATH)
+
+include $(TMK_PATH)/common.mk
+include $(QUANTUM_PATH)/serial_link/tests/rules.mk
+
+$(TEST_OBJ)/$(TEST)_SRC := $($(TEST)_SRC)
+$(TEST_OBJ)/$(TEST)_INC := $($(TEST)_INC) $(VPATH) $(GTEST_INC)
+$(TEST_OBJ)/$(TEST)_DEFS := $($(TEST)_DEFS)
+
+include $(TMK_PATH)/native.mk
+include $(TMK_PATH)/rules.mk
+
+
+$(shell mkdir -p $(BUILD_DIR)/test 2>/dev/null)
+$(shell mkdir -p $(TEST_OBJ) 2>/dev/null)
+
diff --git a/common.mk b/common.mk
new file mode 100644
index 0000000000..18751cd5ac
--- /dev/null
+++ b/common.mk
@@ -0,0 +1,26 @@
+include message.mk
+
+# Directory common source files exist
+TOP_DIR = .
+TMK_DIR = tmk_core
+TMK_PATH = $(TOP_DIR)/$(TMK_DIR)
+LIB_PATH = $(TOP_DIR)/lib
+
+QUANTUM_DIR = quantum
+QUANTUM_PATH = $(TOP_DIR)/$(QUANTUM_DIR)
+
+BUILD_DIR := $(TOP_DIR)/.build
+
+SERIAL_DIR := $(QUANTUM_DIR)/serial_link
+SERIAL_PATH := $(QUANTUM_PATH)/serial_link
+SERIAL_SRC := $(wildcard $(SERIAL_PATH)/protocol/*.c)
+SERIAL_SRC += $(wildcard $(SERIAL_PATH)/system/*.c)
+SERIAL_DEFS += -DSERIAL_LINK_ENABLE
+
+COMMON_VPATH := $(TOP_DIR)
+COMMON_VPATH += $(TMK_PATH)
+COMMON_VPATH += $(QUANTUM_PATH)
+COMMON_VPATH += $(QUANTUM_PATH)/keymap_extras
+COMMON_VPATH += $(QUANTUM_PATH)/audio
+COMMON_VPATH += $(QUANTUM_PATH)/process_keycode
+COMMON_VPATH += $(SERIAL_PATH) \ No newline at end of file
diff --git a/lib/googletest b/lib/googletest
new file mode 160000
+Subproject ec44c6c1675c25b9827aacd08c02433cccde778
diff --git a/message.mk b/message.mk
index fb1a7a1f9a..fa051fd712 100644
--- a/message.mk
+++ b/message.mk
@@ -69,3 +69,11 @@ define GENERATE_MSG_MAKE_KB
endif
endef
MSG_MAKE_KB = $(eval $(call GENERATE_MSG_MAKE_KB))$(MSG_MAKE_KB_ACTUAL)
+define GENERATE_MSG_MAKE_TEST
+ MSG_MAKE_TEST_ACTUAL := Making test $(BOLD)$(TEST_NAME)$(NO_COLOR)
+ ifneq ($$(MAKE_TARGET),)
+ MSG_MAKE_TEST_ACTUAL += with target $(BOLD)$$(MAKE_TARGET)$(NO_COLOR)
+ endif
+endef
+MSG_MAKE_TEST = $(eval $(call GENERATE_MSG_MAKE_TEST))$(MSG_MAKE_TEST_ACTUAL)
+MSG_TEST = Testing $(BOLD)$(TEST_NAME)$(NO_COLOR)
diff --git a/quantum/serial_link/protocol/byte_stuffer.c b/quantum/serial_link/protocol/byte_stuffer.c
index fb4c45a8dc..2c87d64c29 100644
--- a/quantum/serial_link/protocol/byte_stuffer.c
+++ b/quantum/serial_link/protocol/byte_stuffer.c
@@ -31,9 +31,6 @@ SOFTWARE.
// https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing
// http://www.stuartcheshire.org/papers/COBSforToN.pdf
-#define MAX_FRAME_SIZE 1024
-#define NUM_LINKS 2
-
typedef struct byte_stuffer_state {
uint16_t next_zero;
uint16_t data_pos;
diff --git a/quantum/serial_link/protocol/byte_stuffer.h b/quantum/serial_link/protocol/byte_stuffer.h
index 2cc88beb42..97e8968564 100644
--- a/quantum/serial_link/protocol/byte_stuffer.h
+++ b/quantum/serial_link/protocol/byte_stuffer.h
@@ -27,6 +27,9 @@ SOFTWARE.
#include <stdint.h>
+#define MAX_FRAME_SIZE 1024
+#define NUM_LINKS 2
+
void init_byte_stuffer(void);
void byte_stuffer_recv_byte(uint8_t link, uint8_t data);
void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size);
diff --git a/quantum/serial_link/protocol/transport.c b/quantum/serial_link/protocol/transport.c
index f418d11ceb..ff795fe201 100644
--- a/quantum/serial_link/protocol/transport.c
+++ b/quantum/serial_link/protocol/transport.c
@@ -31,6 +31,10 @@ SOFTWARE.
static remote_object_t* remote_objects[MAX_REMOTE_OBJECTS];
static uint32_t num_remote_objects = 0;
+void reinitialize_serial_link_transport(void) {
+ num_remote_objects = 0;
+}
+
void add_remote_objects(remote_object_t** _remote_objects, uint32_t _num_remote_objects) {
unsigned int i;
for(i=0;i<_num_remote_objects;i++) {
diff --git a/quantum/serial_link/protocol/transport.h b/quantum/serial_link/protocol/transport.h
index 9a052d8809..2c5d890b21 100644
--- a/quantum/serial_link/protocol/transport.h
+++ b/quantum/serial_link/protocol/transport.h
@@ -82,7 +82,7 @@ typedef struct { \
remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);\
triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
- return triple_buffer_read_internal(obj->object_size, tb); \
+ return (type*)triple_buffer_read_internal(obj->object_size, tb); \
}
#define MASTER_TO_SINGLE_SLAVE_OBJECT(name, type) \
@@ -112,7 +112,7 @@ typedef struct { \
remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
uint8_t* start = obj->buffer + NUM_SLAVES * LOCAL_OBJECT_SIZE(obj->object_size);\
triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
- return triple_buffer_read_internal(obj->object_size, tb); \
+ return (type*)triple_buffer_read_internal(obj->object_size, tb); \
}
#define SLAVE_TO_MASTER_OBJECT(name, type) \
@@ -139,12 +139,13 @@ typedef struct { \
uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);\
start+=slave * REMOTE_OBJECT_SIZE(obj->object_size); \
triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
- return triple_buffer_read_internal(obj->object_size, tb); \
+ return (type*)triple_buffer_read_internal(obj->object_size, tb); \
}
#define REMOTE_OBJECT(name) (remote_object_t*)&remote_object_##name
void add_remote_objects(remote_object_t** remote_objects, uint32_t num_remote_objects);
+void reinitialize_serial_link_transport(void);
void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size);
void update_transport(void);
diff --git a/quantum/serial_link/tests/byte_stuffer_tests.c b/quantum/serial_link/tests/byte_stuffer_tests.cpp
index 64b170e8c1..ff49d727bb 100644
--- a/quantum/serial_link/tests/byte_stuffer_tests.c
+++ b/quantum/serial_link/tests/byte_stuffer_tests.cpp
@@ -22,70 +22,90 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
-#include <cgreen/cgreen.h>
-#include <cgreen/mocks.h>
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+#include <vector>
+#include <algorithm>
+extern "C" {
#include "serial_link/protocol/byte_stuffer.h"
-#include "serial_link/protocol/byte_stuffer.c"
#include "serial_link/protocol/frame_validator.h"
#include "serial_link/protocol/physical.h"
+}
-static uint8_t sent_data[MAX_FRAME_SIZE*2];
-static uint16_t sent_data_size;
+using testing::_;
+using testing::ElementsAreArray;
+using testing::Args;
-Describe(ByteStuffer);
-BeforeEach(ByteStuffer) {
- init_byte_stuffer();
- sent_data_size = 0;
-}
-AfterEach(ByteStuffer) {}
+class ByteStuffer : public ::testing::Test{
+public:
+ ByteStuffer() {
+ Instance = this;
+ init_byte_stuffer();
+ }
-void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size) {
- mock(data, size);
-}
+ ~ByteStuffer() {
+ Instance = nullptr;
+ }
+
+ MOCK_METHOD3(validator_recv_frame, void (uint8_t link, uint8_t* data, uint16_t size));
+
+ void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
+ std::copy(data, data + size, std::back_inserter(sent_data));
+ }
+ std::vector<uint8_t> sent_data;
-void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
- memcpy(sent_data + sent_data_size, data, size);
- sent_data_size += size;
+ static ByteStuffer* Instance;
+};
+
+ByteStuffer* ByteStuffer::Instance = nullptr;
+
+extern "C" {
+ void validator_recv_frame(uint8_t link, uint8_t* data, uint16_t size) {
+ ByteStuffer::Instance->validator_recv_frame(link, data, size);
+ }
+
+ void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
+ ByteStuffer::Instance->send_data(link, data, size);
+ }
}
-Ensure(ByteStuffer, receives_no_frame_for_a_single_zero_byte) {
- never_expect(validator_recv_frame);
+TEST_F(ByteStuffer, receives_no_frame_for_a_single_zero_byte) {
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .Times(0);
byte_stuffer_recv_byte(0, 0);
}
-Ensure(ByteStuffer, receives_no_frame_for_a_single_FF_byte) {
- never_expect(validator_recv_frame);
+TEST_F(ByteStuffer, receives_no_frame_for_a_single_FF_byte) {
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .Times(0);
byte_stuffer_recv_byte(0, 0xFF);
}
-Ensure(ByteStuffer, receives_no_frame_for_a_single_random_byte) {
- never_expect(validator_recv_frame);
+TEST_F(ByteStuffer, receives_no_frame_for_a_single_random_byte) {
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .Times(0);
byte_stuffer_recv_byte(0, 0x4A);
}
-Ensure(ByteStuffer, receives_no_frame_for_a_zero_length_frame) {
- never_expect(validator_recv_frame);
+TEST_F(ByteStuffer, receives_no_frame_for_a_zero_length_frame) {
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .Times(0);
byte_stuffer_recv_byte(0, 1);
byte_stuffer_recv_byte(0, 0);
}
-Ensure(ByteStuffer, receives_single_byte_valid_frame) {
+TEST_F(ByteStuffer, receives_single_byte_valid_frame) {
uint8_t expected[] = {0x37};
- expect(validator_recv_frame,
- when(size, is_equal_to(1)),
- when(data, is_equal_to_contents_of(expected, 1))
- );
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(expected)));
byte_stuffer_recv_byte(0, 2);
byte_stuffer_recv_byte(0, 0x37);
byte_stuffer_recv_byte(0, 0);
}
-
-Ensure(ByteStuffer, receives_three_bytes_valid_frame) {
+TEST_F(ByteStuffer, receives_three_bytes_valid_frame) {
uint8_t expected[] = {0x37, 0x99, 0xFF};
- expect(validator_recv_frame,
- when(size, is_equal_to(3)),
- when(data, is_equal_to_contents_of(expected, 3))
- );
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(expected)));
byte_stuffer_recv_byte(0, 4);
byte_stuffer_recv_byte(0, 0x37);
byte_stuffer_recv_byte(0, 0x99);
@@ -93,23 +113,19 @@ Ensure(ByteStuffer, receives_three_bytes_valid_frame) {
byte_stuffer_recv_byte(0, 0);
}
-Ensure(ByteStuffer, receives_single_zero_valid_frame) {
+TEST_F(ByteStuffer, receives_single_zero_valid_frame) {
uint8_t expected[] = {0};
- expect(validator_recv_frame,
- when(size, is_equal_to(1)),
- when(data, is_equal_to_contents_of(expected, 1))
- );
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(expected)));
byte_stuffer_recv_byte(0, 1);
byte_stuffer_recv_byte(0, 1);
byte_stuffer_recv_byte(0, 0);
}
-Ensure(ByteStuffer, receives_valid_frame_with_zeroes) {
+TEST_F(ByteStuffer, receives_valid_frame_with_zeroes) {
uint8_t expected[] = {5, 0, 3, 0};
- expect(validator_recv_frame,
- when(size, is_equal_to(4)),
- when(data, is_equal_to_contents_of(expected, 4))
- );
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(expected)));
byte_stuffer_recv_byte(0, 2);
byte_stuffer_recv_byte(0, 5);
byte_stuffer_recv_byte(0, 2);
@@ -118,17 +134,14 @@ Ensure(ByteStuffer, receives_valid_frame_with_zeroes) {
byte_stuffer_recv_byte(0, 0);
}
-Ensure(ByteStuffer, receives_two_valid_frames) {
+
+TEST_F(ByteStuffer, receives_two_valid_frames) {
uint8_t expected1[] = {5, 0};
uint8_t expected2[] = {3};
- expect(validator_recv_frame,
- when(size, is_equal_to(2)),
- when(data, is_equal_to_contents_of(expected1, 2))
- );
- expect(validator_recv_frame,
- when(size, is_equal_to(1)),
- when(data, is_equal_to_contents_of(expected2, 1))
- );
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(expected1)));
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(expected2)));
byte_stuffer_recv_byte(1, 2);
byte_stuffer_recv_byte(1, 5);
byte_stuffer_recv_byte(1, 1);
@@ -138,12 +151,10 @@ Ensure(ByteStuffer, receives_two_valid_frames) {
byte_stuffer_recv_byte(1, 0);
}
-Ensure(ByteStuffer, receives_valid_frame_after_unexpected_zero) {
+TEST_F(ByteStuffer, receives_valid_frame_after_unexpected_zero) {
uint8_t expected[] = {5, 7};
- expect(validator_recv_frame,
- when(size, is_equal_to(2)),
- when(data, is_equal_to_contents_of(expected, 2))
- );
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(expected)));
byte_stuffer_recv_byte(1, 3);
byte_stuffer_recv_byte(1, 1);
byte_stuffer_recv_byte(1, 0);
@@ -153,12 +164,10 @@ Ensure(ByteStuffer, receives_valid_frame_after_unexpected_zero) {
byte_stuffer_recv_byte(1, 0);
}
-Ensure(ByteStuffer, receives_valid_frame_after_unexpected_non_zero) {
+TEST_F(ByteStuffer, receives_valid_frame_after_unexpected_non_zero) {
uint8_t expected[] = {5, 7};
- expect(validator_recv_frame,
- when(size, is_equal_to(2)),
- when(data, is_equal_to_contents_of(expected, 2))
- );
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(expected)));
byte_stuffer_recv_byte(0, 2);
byte_stuffer_recv_byte(0, 9);
byte_stuffer_recv_byte(0, 4); // This should have been zero
@@ -169,16 +178,14 @@ Ensure(ByteStuffer, receives_valid_frame_after_unexpected_non_zero) {
byte_stuffer_recv_byte(0, 0);
}
-Ensure(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_and_then_end_of_frame) {
+TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_and_then_end_of_frame) {
uint8_t expected[254];
int i;
for (i=0;i<254;i++) {
expected[i] = i + 1;
}
- expect(validator_recv_frame,
- when(size, is_equal_to(254)),
- when(data, is_equal_to_contents_of(expected, 254))
- );
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(expected)));
byte_stuffer_recv_byte(0, 0xFF);
for (i=0;i<254;i++) {
byte_stuffer_recv_byte(0, i+1);
@@ -186,17 +193,15 @@ Ensure(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_and_then_end_
byte_stuffer_recv_byte(0, 0);
}
-Ensure(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_non_zero) {
+TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_non_zero) {
uint8_t expected[255];
int i;
for (i=0;i<254;i++) {
expected[i] = i + 1;
}
expected[254] = 7;
- expect(validator_recv_frame,
- when(size, is_equal_to(255)),
- when(data, is_equal_to_contents_of(expected, 255))
- );
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(expected)));
byte_stuffer_recv_byte(0, 0xFF);
for (i=0;i<254;i++) {
byte_stuffer_recv_byte(0, i+1);
@@ -206,17 +211,15 @@ Ensure(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_
byte_stuffer_recv_byte(0, 0);
}
-Ensure(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_zero) {
+TEST_F(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_zero) {
uint8_t expected[255];
int i;
for (i=0;i<254;i++) {
expected[i] = i + 1;
}
expected[254] = 0;
- expect(validator_recv_frame,
- when(size, is_equal_to(255)),
- when(data, is_equal_to_contents_of(expected, 255))
- );
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(expected)));
byte_stuffer_recv_byte(0, 0xFF);
for (i=0;i<254;i++) {
byte_stuffer_recv_byte(0, i+1);
@@ -226,7 +229,7 @@ Ensure(ByteStuffer, receives_a_valid_frame_with_over254_non_zeroes_next_byte_is_
byte_stuffer_recv_byte(0, 0);
}
-Ensure(ByteStuffer, receives_two_long_frames_and_some_more) {
+TEST_F(ByteStuffer, receives_two_long_frames_and_some_more) {
uint8_t expected[515];
int i;
int j;
@@ -238,10 +241,8 @@ Ensure(ByteStuffer, receives_two_long_frames_and_some_more) {
for (i=0;i<7;i++) {
expected[254*2+i] = i + 1;
}
- expect(validator_recv_frame,
- when(size, is_equal_to(515)),
- when(data, is_equal_to_contents_of(expected, 510))
- );
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(expected)));
byte_stuffer_recv_byte(0, 0xFF);
for (i=0;i<254;i++) {
byte_stuffer_recv_byte(0, i+1);
@@ -261,12 +262,10 @@ Ensure(ByteStuffer, receives_two_long_frames_and_some_more) {
byte_stuffer_recv_byte(0, 0);
}
-Ensure(ByteStuffer, receives_an_all_zeros_frame_that_is_maximum_size) {
+TEST_F(ByteStuffer, receives_an_all_zeros_frame_that_is_maximum_size) {
uint8_t expected[MAX_FRAME_SIZE] = {};
- expect(validator_recv_frame,
- when(size, is_equal_to(MAX_FRAME_SIZE)),
- when(data, is_equal_to_contents_of(expected, MAX_FRAME_SIZE))
- );
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(expected)));
int i;
byte_stuffer_recv_byte(0, 1);
for(i=0;i<MAX_FRAME_SIZE;i++) {
@@ -275,9 +274,10 @@ Ensure(ByteStuffer, receives_an_all_zeros_frame_that_is_maximum_size) {
byte_stuffer_recv_byte(0, 0);
}
-Ensure(ByteStuffer, doesnt_recv_a_frame_thats_too_long_all_zeroes) {
+TEST_F(ByteStuffer, doesnt_recv_a_frame_thats_too_long_all_zeroes) {
uint8_t expected[1] = {0};
- never_expect(validator_recv_frame);
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .Times(0);
int i;
byte_stuffer_recv_byte(0, 1);
for(i=0;i<MAX_FRAME_SIZE;i++) {
@@ -287,12 +287,10 @@ Ensure(ByteStuffer, doesnt_recv_a_frame_thats_too_long_all_zeroes) {
byte_stuffer_recv_byte(0, 0);
}
-Ensure(ByteStuffer, received_frame_is_aborted_when_its_too_long) {
+TEST_F(ByteStuffer, received_frame_is_aborted_when_its_too_long) {
uint8_t expected[1] = {1};
- expect(validator_recv_frame,
- when(size, is_equal_to(1)),
- when(data, is_equal_to_contents_of(expected, 1))
- );
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(expected)));
int i;
byte_stuffer_recv_byte(0, 1);
for(i=0;i<MAX_FRAME_SIZE;i++) {
@@ -303,76 +301,68 @@ Ensure(ByteStuffer, received_frame_is_aborted_when_its_too_long) {
byte_stuffer_recv_byte(0, 0);
}
-Ensure(ByteStuffer, does_nothing_when_sending_zero_size_frame) {
- assert_that(sent_data_size, is_equal_to(0));
+TEST_F(ByteStuffer, does_nothing_when_sending_zero_size_frame) {
+ EXPECT_EQ(sent_data.size(), 0);
byte_stuffer_send_frame(0, NULL, 0);
}
-Ensure(ByteStuffer, send_one_byte_frame) {
+TEST_F(ByteStuffer, send_one_byte_frame) {
uint8_t data[] = {5};
byte_stuffer_send_frame(1, data, 1);
uint8_t expected[] = {2, 5, 0};
- assert_that(sent_data_size, is_equal_to(sizeof(expected)));
- assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
+ EXPECT_THAT(sent_data, ElementsAreArray(expected));
}
-Ensure(ByteStuffer, sends_two_byte_frame) {
+TEST_F(ByteStuffer, sends_two_byte_frame) {
uint8_t data[] = {5, 0x77};
byte_stuffer_send_frame(0, data, 2);
uint8_t expected[] = {3, 5, 0x77, 0};
- assert_that(sent_data_size, is_equal_to(sizeof(expected)));
- assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
+ EXPECT_THAT(sent_data, ElementsAreArray(expected));
}
-Ensure(ByteStuffer, sends_one_byte_frame_with_zero) {
+TEST_F(ByteStuffer, sends_one_byte_frame_with_zero) {
uint8_t data[] = {0};
byte_stuffer_send_frame(0, data, 1);
uint8_t expected[] = {1, 1, 0};
- assert_that(sent_data_size, is_equal_to(sizeof(expected)));
- assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
+ EXPECT_THAT(sent_data, ElementsAreArray(expected));
}
-Ensure(ByteStuffer, sends_two_byte_frame_starting_with_zero) {
+TEST_F(ByteStuffer, sends_two_byte_frame_starting_with_zero) {
uint8_t data[] = {0, 9};
byte_stuffer_send_frame(1, data, 2);
uint8_t expected[] = {1, 2, 9, 0};
- assert_that(sent_data_size, is_equal_to(sizeof(expected)));
- assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
+ EXPECT_THAT(sent_data, ElementsAreArray(expected));
}
-Ensure(ByteStuffer, sends_two_byte_frame_starting_with_non_zero) {
+TEST_F(ByteStuffer, sends_two_byte_frame_starting_with_non_zero) {
uint8_t data[] = {9, 0};
byte_stuffer_send_frame(1, data, 2);
uint8_t expected[] = {2, 9, 1, 0};
- assert_that(sent_data_size, is_equal_to(sizeof(expected)));
- assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
+ EXPECT_THAT(sent_data, ElementsAreArray(expected));
}
-Ensure(ByteStuffer, sends_three_byte_frame_zero_in_the_middle) {
+TEST_F(ByteStuffer, sends_three_byte_frame_zero_in_the_middle) {
uint8_t data[] = {9, 0, 0x68};
byte_stuffer_send_frame(0, data, 3);
uint8_t expected[] = {2, 9, 2, 0x68, 0};
- assert_that(sent_data_size, is_equal_to(sizeof(expected)));
- assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
+ EXPECT_THAT(sent_data, ElementsAreArray(expected));
}
-Ensure(ByteStuffer, sends_three_byte_frame_data_in_the_middle) {
+TEST_F(ByteStuffer, sends_three_byte_frame_data_in_the_middle) {
uint8_t data[] = {0, 0x55, 0};
byte_stuffer_send_frame(0, data, 3);
uint8_t expected[] = {1, 2, 0x55, 1, 0};
- assert_that(sent_data_size, is_equal_to(sizeof(expected)));
- assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
+ EXPECT_THAT(sent_data, ElementsAreArray(expected));
}
-Ensure(ByteStuffer, sends_three_byte_frame_with_all_zeroes) {
+TEST_F(ByteStuffer, sends_three_byte_frame_with_all_zeroes) {
uint8_t data[] = {0, 0, 0};
byte_stuffer_send_frame(0, data, 3);
uint8_t expected[] = {1, 1, 1, 1, 0};
- assert_that(sent_data_size, is_equal_to(sizeof(expected)));
- assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
+ EXPECT_THAT(sent_data, ElementsAreArray(expected));
}
-Ensure(ByteStuffer, sends_frame_with_254_non_zeroes) {
+TEST_F(ByteStuffer, sends_frame_with_254_non_zeroes) {
uint8_t data[254];
int i;
for(i=0;i<254;i++) {
@@ -385,11 +375,10 @@ Ensure(ByteStuffer, sends_frame_with_254_non_zeroes) {
expected[i] = i;
}
expected[255] = 0;
- assert_that(sent_data_size, is_equal_to(sizeof(expected)));
- assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
+ EXPECT_THAT(sent_data, ElementsAreArray(expected));
}
-Ensure(ByteStuffer, sends_frame_with_255_non_zeroes) {
+TEST_F(ByteStuffer, sends_frame_with_255_non_zeroes) {
uint8_t data[255];
int i;
for(i=0;i<255;i++) {
@@ -404,17 +393,16 @@ Ensure(ByteStuffer, sends_frame_with_255_non_zeroes) {
expected[255] = 2;
expected[256] = 255;
expected[257] = 0;
- assert_that(sent_data_size, is_equal_to(sizeof(expected)));
- assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
+ EXPECT_THAT(sent_data, ElementsAreArray(expected));
}
-Ensure(ByteStuffer, sends_frame_with_254_non_zeroes_followed_by_zero) {
+TEST_F(ByteStuffer, sends_frame_with_254_non_zeroes_followed_by_zero) {
uint8_t data[255];
int i;
for(i=0;i<254;i++) {
data[i] = i + 1;
}
- data[255] = 0;
+ data[254] = 0;
byte_stuffer_send_frame(0, data, 255);
uint8_t expected[258];
expected[0] = 0xFF;
@@ -424,53 +412,46 @@ Ensure(ByteStuffer, sends_frame_with_254_non_zeroes_followed_by_zero) {
expected[255] = 1;
expected[256] = 1;
expected[257] = 0;
- assert_that(sent_data_size, is_equal_to(sizeof(expected)));
- assert_that(sent_data, is_equal_to_contents_of(expected, sizeof(expected)));
+ EXPECT_THAT(sent_data, ElementsAreArray(expected));
}
-Ensure(ByteStuffer, sends_and_receives_full_roundtrip_small_packet) {
+TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_small_packet) {
uint8_t original_data[] = { 1, 2, 3};
byte_stuffer_send_frame(0, original_data, sizeof(original_data));
- expect(validator_recv_frame,
- when(size, is_equal_to(sizeof(original_data))),
- when(data, is_equal_to_contents_of(original_data, sizeof(original_data)))
- );
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(original_data)));
int i;
- for(i=0;i<sent_data_size;i++) {
- byte_stuffer_recv_byte(1, sent_data[i]);
+ for(auto& d : sent_data) {
+ byte_stuffer_recv_byte(1, d);
}
}
-Ensure(ByteStuffer, sends_and_receives_full_roundtrip_small_packet_with_zeros) {
+TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_small_packet_with_zeros) {
uint8_t original_data[] = { 1, 0, 3, 0, 0, 9};
byte_stuffer_send_frame(1, original_data, sizeof(original_data));
- expect(validator_recv_frame,
- when(size, is_equal_to(sizeof(original_data))),
- when(data, is_equal_to_contents_of(original_data, sizeof(original_data)))
- );
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(original_data)));
int i;
- for(i=0;i<sent_data_size;i++) {
- byte_stuffer_recv_byte(0, sent_data[i]);
+ for(auto& d : sent_data) {
+ byte_stuffer_recv_byte(1, d);
}
}
-Ensure(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes) {
+TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes) {
uint8_t original_data[254];
int i;
for(i=0;i<254;i++) {
original_data[i] = i + 1;
}
byte_stuffer_send_frame(0, original_data, sizeof(original_data));
- expect(validator_recv_frame,
- when(size, is_equal_to(sizeof(original_data))),
- when(data, is_equal_to_contents_of(original_data, sizeof(original_data)))
- );
- for(i=0;i<sent_data_size;i++) {
- byte_stuffer_recv_byte(1, sent_data[i]);
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(original_data)));
+ for(auto& d : sent_data) {
+ byte_stuffer_recv_byte(1, d);
}
}
-Ensure(ByteStuffer, sends_and_receives_full_roundtrip_256_bytes) {
+TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_256_bytes) {
uint8_t original_data[256];
int i;
for(i=0;i<254;i++) {
@@ -479,16 +460,14 @@ Ensure(ByteStuffer, sends_and_receives_full_roundtrip_256_bytes) {
original_data[254] = 22;
original_data[255] = 23;
byte_stuffer_send_frame(0, original_data, sizeof(original_data));
- expect(validator_recv_frame,
- when(size, is_equal_to(sizeof(original_data))),
- when(data, is_equal_to_contents_of(original_data, sizeof(original_data)))
- );
- for(i=0;i<sent_data_size;i++) {
- byte_stuffer_recv_byte(1, sent_data[i]);
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(original_data)));
+ for(auto& d : sent_data) {
+ byte_stuffer_recv_byte(1, d);
}
}
-Ensure(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes_and_then_zero) {
+TEST_F(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes_and_then_zero) {
uint8_t original_data[255];
int i;
for(i=0;i<254;i++) {
@@ -496,11 +475,9 @@ Ensure(ByteStuffer, sends_and_receives_full_roundtrip_254_bytes_and_then_zero) {
}
original_data[254] = 0;
byte_stuffer_send_frame(0, original_data, sizeof(original_data));
- expect(validator_recv_frame,
- when(size, is_equal_to(sizeof(original_data))),
- when(data, is_equal_to_contents_of(original_data, sizeof(original_data)))
- );
- for(i=0;i<sent_data_size;i++) {
- byte_stuffer_recv_byte(1, sent_data[i]);
+ EXPECT_CALL(*this, validator_recv_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(original_data)));
+ for(auto& d : sent_data) {
+ byte_stuffer_recv_byte(1, d);
}
}
diff --git a/quantum/serial_link/tests/frame_router_tests.c b/quantum/serial_link/tests/frame_router_tests.c
deleted file mode 100644
index 6c806fa939..0000000000
--- a/quantum/serial_link/tests/frame_router_tests.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-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.
-
-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.
-*/
-
-#include <cgreen/cgreen.h>
-#include <cgreen/mocks.h>
-#include "serial_link/protocol/byte_stuffer.c"
-#include "serial_link/protocol/frame_validator.c"
-#include "serial_link/protocol/frame_router.c"
-#include "serial_link/protocol/transport.h"
-
-static uint8_t received_data[256];
-static uint16_t received_data_size;
-
-typedef struct {
- uint8_t sent_data[256];
- uint16_t sent_data_size;
-} receive_buffer_t;
-
-typedef struct {
- receive_buffer_t send_buffers[2];
-} router_buffer_t;
-
-router_buffer_t router_buffers[8];
-
-router_buffer_t* current_router_buffer;
-
-
-Describe(FrameRouter);
-BeforeEach(FrameRouter) {
- init_byte_stuffer();
- memset(router_buffers, 0, sizeof(router_buffers));
- current_router_buffer = 0;
-}
-AfterEach(FrameRouter) {}
-
-typedef struct {
- uint32_t data;
- uint8_t extra[16];
-} frame_buffer_t;
-
-
-void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
- receive_buffer_t* buffer = &current_router_buffer->send_buffers[link];
- memcpy(buffer->sent_data + buffer->sent_data_size, data, size);
- buffer->sent_data_size += size;
-}
-
-static void receive_data(uint8_t link, uint8_t* data, uint16_t size) {
- int i;
- for(i=0;i<size;i++) {
- byte_stuffer_recv_byte(link, data[i]);
- }
-}
-
-static void activate_router(uint8_t num) {
- current_router_buffer = router_buffers + num;
- router_set_master(num==0);
-}
-
-static void simulate_transport(uint8_t from, uint8_t to) {
- activate_router(to);
- if (from > to) {
- receive_data(DOWN_LINK,
- router_buffers[from].send_buffers[UP_LINK].sent_data,
- router_buffers[from].send_buffers[UP_LINK].sent_data_size);
- }
- else if(to > from) {
- receive_data(UP_LINK,
- router_buffers[from].send_buffers[DOWN_LINK].sent_data,
- router_buffers[from].send_buffers[DOWN_LINK].sent_data_size);
- }
-}
-
-void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size) {
- mock(from, data, size);
-}
-
-
-Ensure(FrameRouter, master_broadcast_is_received_by_everyone) {
- frame_buffer_t data;
- data.data = 0xAB7055BB;
- activate_router(0);
- router_send_frame(0xFF, (uint8_t*)&data, 4);
- assert_that(router_buffers[0].send_buffers[DOWN_LINK].sent_data_size, is_greater_than(0));
- assert_that(router_buffers[0].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
-
- expect(transport_recv_frame,
- when(from, is_equal_to(0)),
- when(size, is_equal_to(4)),
- when(data, is_equal_to_contents_of(&data.data, 4))
- );
- simulate_transport(0, 1);
- assert_that(router_buffers[1].send_buffers[DOWN_LINK].sent_data_size, is_greater_than(0));
- assert_that(router_buffers[1].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
-
- expect(transport_recv_frame,
- when(from, is_equal_to(0)),
- when(size, is_equal_to(4)),
- when(data, is_equal_to_contents_of(&data.data, 4))
- );
- simulate_transport(1, 2);
- assert_that(router_buffers[2].send_buffers[DOWN_LINK].sent_data_size, is_greater_than(0));
- assert_that(router_buffers[2].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
-}
-
-Ensure(FrameRouter, master_send_is_received_by_targets) {
- frame_buffer_t data;
- data.data = 0xAB7055BB;
- activate_router(0);
- router_send_frame((1 << 1) | (1 << 2), (uint8_t*)&data, 4);
- assert_that(router_buffers[0].send_buffers[DOWN_LINK].sent_data_size, is_greater_than(0));
- assert_that(router_buffers[0].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
-
- simulate_transport(0, 1);
- assert_that(router_buffers[1].send_buffers[DOWN_LINK].sent_data_size, is_greater_than(0));
- assert_that(router_buffers[1].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
-
- expect(transport_recv_frame,
- when(from, is_equal_to(0)),
- when(size, is_equal_to(4)),
- when(data, is_equal_to_contents_of(&data.data, 4))
- );
- simulate_transport(1, 2);
- assert_that(router_buffers[2].send_buffers[DOWN_LINK].sent_data_size, is_greater_than(0));
- assert_that(router_buffers[2].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
-
- expect(transport_recv_frame,
- when(from, is_equal_to(0)),
- when(size, is_equal_to(4)),
- when(data, is_equal_to_contents_of(&data.data, 4))
- );
- simulate_transport(2, 3);
- assert_that(router_buffers[3].send_buffers[DOWN_LINK].sent_data_size, is_greater_than(0));
- assert_that(router_buffers[3].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
-}
-
-Ensure(FrameRouter, first_link_sends_to_master) {
- frame_buffer_t data;
- data.data = 0xAB7055BB;
- activate_router(1);
- router_send_frame(0, (uint8_t*)&data, 4);
- assert_that(router_buffers[1].send_buffers[UP_LINK].sent_data_size, is_greater_than(0));
- assert_that(router_buffers[1].send_buffers[DOWN_LINK].sent_data_size, is_equal_to(0));
-
- expect(transport_recv_frame,
- when(from, is_equal_to(1)),
- when(size, is_equal_to(4)),
- when(data, is_equal_to_contents_of(&data.data, 4))
- );
- simulate_transport(1, 0);
- assert_that(router_buffers[0].send_buffers[DOWN_LINK].sent_data_size, is_equal_to(0));
- assert_that(router_buffers[0].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
-}
-
-Ensure(FrameRouter, second_link_sends_to_master) {
- frame_buffer_t data;
- data.data = 0xAB7055BB;
- activate_router(2);
- router_send_frame(0, (uint8_t*)&data, 4);
- assert_that(router_buffers[2].send_buffers[UP_LINK].sent_data_size, is_greater_than(0));
- assert_that(router_buffers[2].send_buffers[DOWN_LINK].sent_data_size, is_equal_to(0));
-
- simulate_transport(2, 1);
- assert_that(router_buffers[1].send_buffers[UP_LINK].sent_data_size, is_greater_than(0));
- assert_that(router_buffers[1].send_buffers[DOWN_LINK].sent_data_size, is_equal_to(0));
-
- expect(transport_recv_frame,
- when(from, is_equal_to(2)),
- when(size, is_equal_to(4)),
- when(data, is_equal_to_contents_of(&data.data, 4))
- );
- simulate_transport(1, 0);
- assert_that(router_buffers[0].send_buffers[DOWN_LINK].sent_data_size, is_equal_to(0));
- assert_that(router_buffers[0].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
-}
-
-Ensure(FrameRouter, master_sends_to_master_does_nothing) {
- frame_buffer_t data;
- data.data = 0xAB7055BB;
- activate_router(0);
- router_send_frame(0, (uint8_t*)&data, 4);
- assert_that(router_buffers[0].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
- assert_that(router_buffers[0].send_buffers[DOWN_LINK].sent_data_size, is_equal_to(0));
-}
-
-Ensure(FrameRouter, link_sends_to_other_link_does_nothing) {
- frame_buffer_t data;
- data.data = 0xAB7055BB;
- activate_router(1);
- router_send_frame(2, (uint8_t*)&data, 4);
- assert_that(router_buffers[1].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
- assert_that(router_buffers[1].send_buffers[DOWN_LINK].sent_data_size, is_equal_to(0));
-}
-
-Ensure(FrameRouter, master_receives_on_uplink_does_nothing) {
- frame_buffer_t data;
- data.data = 0xAB7055BB;
- activate_router(1);
- router_send_frame(0, (uint8_t*)&data, 4);
- assert_that(router_buffers[1].send_buffers[UP_LINK].sent_data_size, is_greater_than(0));
- assert_that(router_buffers[1].send_buffers[DOWN_LINK].sent_data_size, is_equal_to(0));
-
- never_expect(transport_recv_frame);
- activate_router(0);
- receive_data(UP_LINK,
- router_buffers[1].send_buffers[UP_LINK].sent_data,
- router_buffers[1].send_buffers[UP_LINK].sent_data_size);
- assert_that(router_buffers[0].send_buffers[UP_LINK].sent_data_size, is_equal_to(0));
- assert_that(router_buffers[0].send_buffers[DOWN_LINK].sent_data_size, is_equal_to(0));
-}
diff --git a/quantum/serial_link/tests/frame_router_tests.cpp b/quantum/serial_link/tests/frame_router_tests.cpp
new file mode 100644
index 0000000000..2bd5bf830d
--- /dev/null
+++ b/quantum/serial_link/tests/frame_router_tests.cpp
@@ -0,0 +1,229 @@
+/*
+The MIT License (MIT)
+
+Copyright (c) 2016 Fred Sundvik
+
+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.
+
+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.
+*/
+
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+#include <array>
+extern "C" {
+ #include "serial_link/protocol/transport.h"
+ #include "serial_link/protocol/byte_stuffer.h"
+ #include "serial_link/protocol/frame_router.h"
+}
+
+using testing::_;
+using testing::ElementsAreArray;
+using testing::Args;
+
+class FrameRouter : public testing::Test {
+public:
+ FrameRouter() :
+ current_router_buffer(nullptr)
+ {
+ Instance = this;
+ init_byte_stuffer();
+ }
+
+ ~FrameRouter() {
+ Instance = nullptr;
+ }
+
+ void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
+ auto& buffer = current_router_buffer->send_buffers[link];
+ std::copy(data, data + size, std::back_inserter(buffer));
+ }
+
+ void receive_data(uint8_t link, uint8_t* data, uint16_t size) {
+ int i;
+ for(i=0;i<size;i++) {
+ byte_stuffer_recv_byte(link, data[i]);
+ }
+ }
+
+ void activate_router(uint8_t num) {
+ current_router_buffer = router_buffers + num;
+ router_set_master(num==0);
+ }
+
+ void simulate_transport(uint8_t from, uint8_t to) {
+ activate_router(to);
+ if (from > to) {
+ receive_data(DOWN_LINK,
+ router_buffers[from].send_buffers[UP_LINK].data(),
+ router_buffers[from].send_buffers[UP_LINK].size());
+ }
+ else if(to > from) {
+ receive_data(UP_LINK,
+ router_buffers[from].send_buffers[DOWN_LINK].data(),
+ router_buffers[from].send_buffers[DOWN_LINK].size());
+ }
+ }
+
+ MOCK_METHOD3(transport_recv_frame, void (uint8_t from, uint8_t* data, uint16_t size));
+
+ std::vector<uint8_t> received_data;
+
+ struct router_buffer {
+ std::vector<uint8_t> send_buffers[2];
+ };
+
+ router_buffer router_buffers[8];
+ router_buffer* current_router_buffer;
+
+ static FrameRouter* Instance;
+};
+
+FrameRouter* FrameRouter::Instance = nullptr;
+
+
+typedef struct {
+ std::array<uint8_t, 4> data;
+ uint8_t extra[16];
+} frame_buffer_t;
+
+
+extern "C" {
+ void send_data(uint8_t link, const uint8_t* data, uint16_t size) {
+ FrameRouter::Instance->send_data(link, data, size);
+ }
+
+
+ void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size) {
+ FrameRouter::Instance->transport_recv_frame(from, data, size);
+ }
+}
+
+TEST_F(FrameRouter, master_broadcast_is_received_by_everyone) {
+ frame_buffer_t data;
+ data.data = {0xAB, 0x70, 0x55, 0xBB};
+ activate_router(0);
+ router_send_frame(0xFF, (uint8_t*)&data, 4);
+ EXPECT_GT(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
+ EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
+ EXPECT_CALL(*this, transport_recv_frame(0, _, _))
+ .With(Args<1, 2>(ElementsAreArray(data.data)));
+ simulate_transport(0, 1);
+ EXPECT_GT(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
+ EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0);
+
+ EXPECT_CALL(*this, transport_recv_frame(0, _, _))
+ .With(Args<1, 2>(ElementsAreArray(data.data)));
+ simulate_transport(1, 2);
+ EXPECT_GT(router_buffers[2].send_buffers[DOWN_LINK].size(), 0);
+ EXPECT_EQ(router_buffers[2].send_buffers[UP_LINK].size(), 0);
+}
+
+TEST_F(FrameRouter, master_send_is_received_by_targets) {
+ frame_buffer_t data;
+ data.data = {0xAB, 0x70, 0x55, 0xBB};
+ activate_router(0);
+ router_send_frame((1 << 1) | (1 << 2), (uint8_t*)&data, 4);
+ EXPECT_GT(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
+ EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
+
+ simulate_transport(0, 1);
+ EXPECT_GT(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
+ EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0);
+
+ EXPECT_CALL(*this, transport_recv_frame(0, _, _))
+ .With(Args<1, 2>(ElementsAreArray(data.data)));
+ simulate_transport(1, 2);
+ EXPECT_GT(router_buffers[2].send_buffers[DOWN_LINK].size(), 0);
+ EXPECT_EQ(router_buffers[2].send_buffers[UP_LINK].size(), 0);
+
+ EXPECT_CALL(*this, transport_recv_frame(0, _, _))
+ .With(Args<1, 2>(ElementsAreArray(data.data)));
+ simulate_transport(2, 3);
+ EXPECT_GT(router_buffers[3].send_buffers[DOWN_LINK].size(), 0);
+ EXPECT_EQ(router_buffers[3].send_buffers[UP_LINK].size(), 0);
+}
+
+TEST_F(FrameRouter, first_link_sends_to_master) {
+ frame_buffer_t data;
+ data.data = {0xAB, 0x70, 0x55, 0xBB};
+ activate_router(1);
+ router_send_frame(0, (uint8_t*)&data, 4);
+ EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0);
+ EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
+
+ EXPECT_CALL(*this, transport_recv_frame(1, _, _))
+ .With(Args<1, 2>(ElementsAreArray(data.data)));
+ simulate_transport(1, 0);
+ EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
+ EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
+}
+
+TEST_F(FrameRouter, second_link_sends_to_master) {
+ frame_buffer_t data;
+ data.data = {0xAB, 0x70, 0x55, 0xBB};
+ activate_router(2);
+ router_send_frame(0, (uint8_t*)&data, 4);
+ EXPECT_GT(router_buffers[2].send_buffers[UP_LINK].size(), 0);
+ EXPECT_EQ(router_buffers[2].send_buffers[DOWN_LINK].size(), 0);
+
+ simulate_transport(2, 1);
+ EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0);
+ EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
+
+ EXPECT_CALL(*this, transport_recv_frame(2, _, _))
+ .With(Args<1, 2>(ElementsAreArray(data.data)));
+ simulate_transport(1, 0);
+ EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
+ EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
+}
+
+TEST_F(FrameRouter, master_sends_to_master_does_nothing) {
+ frame_buffer_t data;
+ data.data = {0xAB, 0x70, 0x55, 0xBB};
+ activate_router(0);
+ router_send_frame(0, (uint8_t*)&data, 4);
+ EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
+ EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
+}
+
+TEST_F(FrameRouter, link_sends_to_other_link_does_nothing) {
+ frame_buffer_t data;
+ data.data = {0xAB, 0x70, 0x55, 0xBB};
+ activate_router(1);
+ router_send_frame(2, (uint8_t*)&data, 4);
+ EXPECT_EQ(router_buffers[1].send_buffers[UP_LINK].size(), 0);
+ EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
+}
+
+TEST_F(FrameRouter, master_receives_on_uplink_does_nothing) {
+ frame_buffer_t data;
+ data.data = {0xAB, 0x70, 0x55, 0xBB};
+ activate_router(1);
+ router_send_frame(0, (uint8_t*)&data, 4);
+ EXPECT_GT(router_buffers[1].send_buffers[UP_LINK].size(), 0);
+ EXPECT_EQ(router_buffers[1].send_buffers[DOWN_LINK].size(), 0);
+
+ EXPECT_CALL(*this, transport_recv_frame(_, _, _))
+ .Times(0);
+ activate_router(0);
+ receive_data(UP_LINK,
+ router_buffers[1].send_buffers[UP_LINK].data(),
+ router_buffers[1].send_buffers[UP_LINK].size());
+ EXPECT_EQ(router_buffers[0].send_buffers[UP_LINK].size(), 0);
+ EXPECT_EQ(router_buffers[0].send_buffers[DOWN_LINK].size(), 0);
+}
diff --git a/quantum/serial_link/tests/frame_validator_tests.c b/quantum/serial_link/tests/frame_validator_tests.cpp
index d20947e2c9..9223af83b0 100644
--- a/quantum/serial_link/tests/frame_validator_tests.c
+++ b/quantum/serial_link/tests/frame_validator_tests.cpp
@@ -22,24 +22,47 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
-#include <cgreen/cgreen.h>
-#include <cgreen/mocks.h>
-#include "serial_link/protocol/frame_validator.c"
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+extern "C" {
+#include "serial_link/protocol/frame_validator.h"
+}
+
+using testing::_;
+using testing::ElementsAreArray;
+using testing::Args;
+
+class FrameValidator : public testing::Test {
+public:
+ FrameValidator() {
+ Instance = this;
+ }
+
+ ~FrameValidator() {
+ Instance = nullptr;
+ }
+
+ MOCK_METHOD3(route_incoming_frame, void (uint8_t link, uint8_t* data, uint16_t size));
+ MOCK_METHOD3(byte_stuffer_send_frame, void (uint8_t link, uint8_t* data, uint16_t size));
+ static FrameValidator* Instance;
+};
+
+FrameValidator* FrameValidator::Instance = nullptr;
+
+extern "C" {
void route_incoming_frame(uint8_t link, uint8_t* data, uint16_t size) {
- mock(data, size);
+ FrameValidator::Instance->route_incoming_frame(link, data, size);
}
void byte_stuffer_send_frame(uint8_t link, uint8_t* data, uint16_t size) {
- mock(data, size);
+ FrameValidator::Instance->byte_stuffer_send_frame(link, data, size);
+}
}
-Describe(FrameValidator);
-BeforeEach(FrameValidator) {}
-AfterEach(FrameValidator) {}
-
-Ensure(FrameValidator, doesnt_validate_frames_under_5_bytes) {
- never_expect(route_incoming_frame);
+TEST_F(FrameValidator, doesnt_validate_frames_under_5_bytes) {
+ EXPECT_CALL(*this, route_incoming_frame(_, _, _))
+ .Times(0);
uint8_t data[] = {1, 2};
validator_recv_frame(0, 0, 1);
validator_recv_frame(0, data, 2);
@@ -47,55 +70,46 @@ Ensure(FrameValidator, doesnt_validate_frames_under_5_bytes) {
validator_recv_frame(0, data, 4);
}
-Ensure(FrameValidator, validates_one_byte_frame_with_correct_crc) {
+TEST_F(FrameValidator, validates_one_byte_frame_with_correct_crc) {
uint8_t data[] = {0x44, 0x04, 0x6A, 0xB3, 0xA3};
- expect(route_incoming_frame,
- when(size, is_equal_to(1)),
- when(data, is_equal_to_contents_of(data, 1))
- );
+ EXPECT_CALL(*this, route_incoming_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(data, 1)));
validator_recv_frame(0, data, 5);
}
-Ensure(FrameValidator, does_not_validate_one_byte_frame_with_incorrect_crc) {
+TEST_F(FrameValidator, does_not_validate_one_byte_frame_with_incorrect_crc) {
uint8_t data[] = {0x44, 0, 0, 0, 0};
- never_expect(route_incoming_frame);
+ EXPECT_CALL(*this, route_incoming_frame(_, _, _))
+ .Times(0);
validator_recv_frame(1, data, 5);
}
-Ensure(FrameValidator, validates_four_byte_frame_with_correct_crc) {
+TEST_F(FrameValidator, validates_four_byte_frame_with_correct_crc) {
uint8_t data[] = {0x44, 0x10, 0xFF, 0x00, 0x74, 0x4E, 0x30, 0xBA};
- expect(route_incoming_frame,
- when(size, is_equal_to(4)),
- when(data, is_equal_to_contents_of(data, 4))
- );
+ EXPECT_CALL(*this, route_incoming_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(data, 4)));
validator_recv_frame(1, data, 8);
}
-Ensure(FrameValidator, validates_five_byte_frame_with_correct_crc) {
+TEST_F(FrameValidator, validates_five_byte_frame_with_correct_crc) {
uint8_t data[] = {1, 2, 3, 4, 5, 0xF4, 0x99, 0x0B, 0x47};
- expect(route_incoming_frame,
- when(size, is_equal_to(5)),
- when(data, is_equal_to_contents_of(data, 5))
- );
+ EXPECT_CALL(*this, route_incoming_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(data, 5)));
validator_recv_frame(0, data, 9);
}
-Ensure(FrameValidator, sends_one_byte_with_correct_crc) {
+TEST_F(FrameValidator, sends_one_byte_with_correct_crc) {
uint8_t original[] = {0x44, 0, 0, 0, 0};
uint8_t expected[] = {0x44, 0x04, 0x6A, 0xB3, 0xA3};
- expect(byte_stuffer_send_frame,
- when(size, is_equal_to(sizeof(expected))),
- when(data, is_equal_to_contents_of(expected, sizeof(expected)))
- );
+ EXPECT_CALL(*this, byte_stuffer_send_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(expected)));
validator_send_frame(0, original, 1);
}
-Ensure(FrameValidator, sends_five_bytes_with_correct_crc) {
+TEST_F(FrameValidator, sends_five_bytes_with_correct_crc) {
uint8_t original[] = {1, 2, 3, 4, 5, 0, 0, 0, 0};
uint8_t expected[] = {1, 2, 3, 4, 5, 0xF4, 0x99, 0x0B, 0x47};
- expect(byte_stuffer_send_frame,
- when(size, is_equal_to(sizeof(expected))),
- when(data, is_equal_to_contents_of(expected, sizeof(expected)))
- );
+ EXPECT_CALL(*this, byte_stuffer_send_frame(_, _, _))
+ .With(Args<1, 2>(ElementsAreArray(expected)));
validator_send_frame(0, original, 5);
}
diff --git a/quantum/serial_link/tests/rules.mk b/quantum/serial_link/tests/rules.mk
new file mode 100644
index 0000000000..b81515bc55
--- /dev/null
+++ b/quantum/serial_link/tests/rules.mk
@@ -0,0 +1,22 @@
+serial_link_byte_stuffer_SRC :=\
+ $(SERIAL_PATH)/tests/byte_stuffer_tests.cpp \
+ $(SERIAL_PATH)/protocol/byte_stuffer.c
+
+serial_link_frame_validator_SRC := \
+ $(SERIAL_PATH)/tests/frame_validator_tests.cpp \
+ $(SERIAL_PATH)/protocol/frame_validator.c
+
+serial_link_frame_router_SRC := \
+ $(SERIAL_PATH)/tests/frame_router_tests.cpp \
+ $(SERIAL_PATH)/protocol/byte_stuffer.c \
+ $(SERIAL_PATH)/protocol/frame_validator.c \
+ $(SERIAL_PATH)/protocol/frame_router.c
+
+serial_link_triple_buffered_object_SRC := \
+ $(SERIAL_PATH)/tests/triple_buffered_object_tests.cpp \
+ $(SERIAL_PATH)/protocol/triple_buffered_object.c
+
+serial_link_transport_SRC := \
+ $(SERIAL_PATH)/tests/transport_tests.cpp \
+ $(SERIAL_PATH)/protocol/transport.c \
+ $(SERIAL_PATH)/protocol/triple_buffered_object.c
diff --git a/quantum/serial_link/tests/testlist.mk b/quantum/serial_link/tests/testlist.mk
new file mode 100644
index 0000000000..a80e888849
--- /dev/null
+++ b/quantum/serial_link/tests/testlist.mk
@@ -0,0 +1,6 @@
+TEST_LIST +=\
+ serial_link_byte_stuffer\
+ serial_link_frame_validator\
+ serial_link_frame_router\
+ serial_link_triple_buffered_object\
+ serial_link_transport \ No newline at end of file
diff --git a/quantum/serial_link/tests/transport_tests.c b/quantum/serial_link/tests/transport_tests.c
deleted file mode 100644
index 358e1b9fd4..0000000000
--- a/quantum/serial_link/tests/transport_tests.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Fred Sundvik
-
-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.
-
-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.
-*/
-
-#include <cgreen/cgreen.h>
-#include <cgreen/mocks.h>
-#include "serial_link/protocol/transport.c"
-#include "serial_link/protocol/triple_buffered_object.c"
-
-void signal_data_written(void) {
- mock();
-}
-
-static uint8_t sent_data[2048];
-static uint16_t sent_data_size;
-
-void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) {
- mock(destination);
- memcpy(sent_data + sent_data_size, data, size);
- sent_data_size += size;
-}
-
-typedef struct {
- uint32_t test;
-} test_object1_t;
-
-typedef struct {
- uint32_t test1;
- uint32_t test2;
-} test_object2_t;
-
-MASTER_TO_ALL_SLAVES_OBJECT(master_to_slave, test_object1_t);
-MASTER_TO_SINGLE_SLAVE_OBJECT(master_to_single_slave, test_object1_t);
-SLAVE_TO_MASTER_OBJECT(slave_to_master, test_object1_t);
-
-static remote_object_t* test_remote_objects[] = {
- REMOTE_OBJECT(master_to_slave),
- REMOTE_OBJECT(master_to_single_slave),
- REMOTE_OBJECT(slave_to_master),
-};
-
-Describe(Transport);
-BeforeEach(Transport) {
- add_remote_objects(test_remote_objects, sizeof(test_remote_objects) / sizeof(remote_object_t*));
- sent_data_size = 0;
-}
-AfterEach(Transport) {}
-
-Ensure(Transport, write_to_local_signals_an_event) {
- begin_write_master_to_slave();
- expect(signal_data_written);
- end_write_master_to_slave();
- begin_write_slave_to_master();
- expect(signal_data_written);
- end_write_slave_to_master();
- begin_write_master_to_single_slave(1);
- expect(signal_data_written);
- end_write_master_to_single_slave(1);
-}
-
-Ensure(Transport, writes_from_master_to_all_slaves) {
- update_transport();
- test_object1_t* obj = begin_write_master_to_slave();
- obj->test = 5;
- expect(signal_data_written);
- end_write_master_to_slave();
- expect(router_send_frame,
- when(destination, is_equal_to(0xFF)));
- update_transport();
- transport_recv_frame(0, sent_data, sent_data_size);
- test_object1_t* obj2 = read_master_to_slave();
- assert_that(obj2, is_not_equal_to(NULL));
- assert_that(obj2->test, is_equal_to(5));
-}
-
-Ensure(Transport, writes_from_slave_to_master) {
- update_transport();
- test_object1_t* obj = begin_write_slave_to_master();
- obj->test = 7;
- expect(signal_data_written);
- end_write_slave_to_master();
- expect(router_send_frame,
- when(destination, is_equal_to(0)));
- update_transport();
- transport_recv_frame(3, sent_data, sent_data_size);
- test_object1_t* obj2 = read_slave_to_master(2);
- assert_that(read_slave_to_master(0), is_equal_to(NULL));
- assert_that(obj2, is_not_equal_to(NULL));
- assert_that(obj2->test, is_equal_to(7));
-}
-
-Ensure(Transport, writes_from_master_to_single_slave) {
- update_transport();
- test_object1_t* obj = begin_write_master_to_single_slave(3);
- obj->test = 7;
- expect(signal_data_written);
- end_write_master_to_single_slave(3);
- expect(router_send_frame,
- when(destination, is_equal_to(4)));
- update_transport();
- transport_recv_frame(0, sent_data, sent_data_size);
- test_object1_t* obj2 = read_master_to_single_slave();
- assert_that(obj2, is_not_equal_to(NULL));
- assert_that(obj2->test, is_equal_to(7));
-}
-
-Ensure(Transport, ignores_object_with_invalid_id) {
- update_transport();
- test_object1_t* obj = begin_write_master_to_single_slave(3);
- obj->test = 7;
- expect(signal_data_written);
- end_write_master_to_single_slave(3);
- expect(router_send_frame,
- when(destination, is_equal_to(4)));
- update_transport();
- sent_data[sent_data_size - 1] = 44;
- transport_recv_frame(0, sent_data, sent_data_size);
- test_object1_t* obj2 = read_master_to_single_slave();
- assert_that(obj2, is_equal_to(NULL));
-}
-
-Ensure(Transport, ignores_object_with_size_too_small) {
- update_transport();
- test_object1_t* obj = begin_write_master_to_slave();
- obj->test = 7;
- expect(signal_data_written);
- end_write_master_to_slave();
- expect(router_send_frame);
- update_transport();
- sent_data[sent_data_size - 2] = 0;
- transport_recv_frame(0, sent_data, sent_data_size - 1);
- test_object1_t* obj2 = read_master_to_slave();
- assert_that(obj2, is_equal_to(NULL));
-}
-
-Ensure(Transport, ignores_object_with_size_too_big) {
- update_transport();
- test_object1_t* obj = begin_write_master_to_slave();
- obj->test = 7;
- expect(signal_data_written);
- end_write_master_to_slave();
- expect(router_send_frame);
- update_transport();
- sent_data[sent_data_size + 21] = 0;
- transport_recv_frame(0, sent_data, sent_data_size + 22);
- test_object1_t* obj2 = read_master_to_slave();
- assert_that(obj2, is_equal_to(NULL));
-}
diff --git a/quantum/serial_link/tests/transport_tests.cpp b/quantum/serial_link/tests/transport_tests.cpp
new file mode 100644
index 0000000000..21b7b165f6
--- /dev/null
+++ b/quantum/serial_link/tests/transport_tests.cpp
@@ -0,0 +1,188 @@
+/*
+The MIT License (MIT)
+
+Copyright (c) 2016 Fred Sundvik
+
+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.
+
+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.
+*/
+
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+
+using testing::_;
+using testing::ElementsAreArray;
+using testing::Args;
+
+extern "C" {
+#include "serial_link/protocol/transport.h"
+}
+
+struct test_object1 {
+ uint32_t test;
+};
+
+struct test_object2 {
+ uint32_t test1;
+ uint32_t test2;
+};
+
+MASTER_TO_ALL_SLAVES_OBJECT(master_to_slave, test_object1);
+MASTER_TO_SINGLE_SLAVE_OBJECT(master_to_single_slave, test_object1);
+SLAVE_TO_MASTER_OBJECT(slave_to_master, test_object1);
+
+static remote_object_t* test_remote_objects[] = {
+ REMOTE_OBJECT(master_to_slave),
+ REMOTE_OBJECT(master_to_single_slave),
+ REMOTE_OBJECT(slave_to_master),
+};
+
+class Transport : public testing::Test {
+public:
+ Transport() {
+ Instance = this;
+ add_remote_objects(test_remote_objects, sizeof(test_remote_objects) / sizeof(remote_object_t*));
+ }
+
+ ~Transport() {
+ Instance = nullptr;
+ reinitialize_serial_link_transport();
+ }
+
+ MOCK_METHOD0(signal_data_written, void ());
+ MOCK_METHOD1(router_send_frame, void (uint8_t destination));
+
+ void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) {
+ router_send_frame(destination);
+ std::copy(data, data + size, std::back_inserter(sent_data));
+ }
+
+ static Transport* Instance;
+
+ std::vector<uint8_t> sent_data;
+};
+
+Transport* Transport::Instance = nullptr;
+
+extern "C" {
+void signal_data_written(void) {
+ Transport::Instance->signal_data_written();
+}
+
+void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) {
+ Transport::Instance->router_send_frame(destination, data, size);
+}
+}
+
+TEST_F(Transport, write_to_local_signals_an_event) {
+ begin_write_master_to_slave();
+ EXPECT_CALL(*this, signal_data_written());
+ end_write_master_to_slave();
+ begin_write_slave_to_master();
+ EXPECT_CALL(*this, signal_data_written());
+ end_write_slave_to_master();
+ begin_write_master_to_single_slave(1);
+ EXPECT_CALL(*this, signal_data_written());
+ end_write_master_to_single_slave(1);
+}
+
+TEST_F(Transport, writes_from_master_to_all_slaves) {
+ update_transport();
+ test_object1* obj = begin_write_master_to_slave();
+ obj->test = 5;
+ EXPECT_CALL(*this, signal_data_written());
+ end_write_master_to_slave();
+ EXPECT_CALL(*this, router_send_frame(0xFF));
+ update_transport();
+ transport_recv_frame(0, sent_data.data(), sent_data.size());
+ test_object1* obj2 = read_master_to_slave();
+ EXPECT_NE(obj2, nullptr);
+ EXPECT_EQ(obj2->test, 5);
+}
+
+TEST_F(Transport, writes_from_slave_to_master) {
+ update_transport();
+ test_object1* obj = begin_write_slave_to_master();
+ obj->test = 7;
+ EXPECT_CALL(*this, signal_data_written());
+ end_write_slave_to_master();
+ EXPECT_CALL(*this, router_send_frame(0));
+ update_transport();
+ transport_recv_frame(3, sent_data.data(), sent_data.size());
+ test_object1* obj2 = read_slave_to_master(2);
+ EXPECT_EQ(read_slave_to_master(0), nullptr);
+ EXPECT_NE(obj2, nullptr);
+ EXPECT_EQ(obj2->test, 7);
+}
+
+TEST_F(Transport, writes_from_master_to_single_slave) {
+ update_transport();
+ test_object1* obj = begin_write_master_to_single_slave(3);
+ obj->test = 7;
+ EXPECT_CALL(*this, signal_data_written());
+ end_write_master_to_single_slave(3);
+ EXPECT_CALL(*this, router_send_frame(4));
+ update_transport();
+ transport_recv_frame(0, sent_data.data(), sent_data.size());
+ test_object1* obj2 = read_master_to_single_slave();
+ EXPECT_NE(obj2, nullptr);
+ EXPECT_EQ(obj2->test, 7);
+}
+
+TEST_F(Transport, ignores_object_with_invalid_id) {
+ update_transport();
+ test_object1* obj = begin_write_master_to_single_slave(3);
+ obj->test = 7;
+ EXPECT_CALL(*this, signal_data_written());
+ end_write_master_to_single_slave(3);
+ EXPECT_CALL(*this, router_send_frame(4));
+ update_transport();
+ sent_data[sent_data.size() - 1] = 44;
+ transport_recv_frame(0, sent_data.data(), sent_data.size());
+ test_object1* obj2 = read_master_to_single_slave();
+ EXPECT_EQ(obj2, nullptr);
+}
+
+TEST_F(Transport, ignores_object_with_size_too_small) {
+ update_transport();
+ test_object1* obj = begin_write_master_to_slave();
+ obj->test = 7;
+ EXPECT_CALL(*this, signal_data_written());
+ end_write_master_to_slave();
+ EXPECT_CALL(*this, router_send_frame(_));
+ update_transport();
+ sent_data[sent_data.size() - 2] = 0;
+ transport_recv_frame(0, sent_data.data(), sent_data.size() - 1);
+ test_object1* obj2 = read_master_to_slave();
+ EXPECT_EQ(obj2, nullptr);
+}
+
+TEST_F(Transport, ignores_object_with_size_too_big) {
+ update_transport();
+ test_object1* obj = begin_write_master_to_slave();
+ obj->test = 7;
+ EXPECT_CALL(*this, signal_data_written());
+ end_write_master_to_slave();
+ EXPECT_CALL(*this, router_send_frame(_));
+ update_transport();
+ sent_data.resize(sent_data.size() + 22);
+ sent_data[sent_data.size() - 1] = 0;
+ transport_recv_frame(0, sent_data.data(), sent_data.size());
+ test_object1* obj2 = read_master_to_slave();
+ EXPECT_EQ(obj2, nullptr);
+}
diff --git a/quantum/serial_link/tests/triple_buffered_object_tests.c b/quantum/serial_link/tests/triple_buffered_object_tests.cpp
index 6f7c82b468..7724bbee9c 100644
--- a/quantum/serial_link/tests/triple_buffered_object_tests.c
+++ b/quantum/serial_link/tests/triple_buffered_object_tests.cpp
@@ -22,53 +22,55 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
-#include <cgreen/cgreen.h>
-#include "serial_link/protocol/triple_buffered_object.c"
+#include "gtest/gtest.h"
+extern "C" {
+#include "serial_link/protocol/triple_buffered_object.h"
+}
-typedef struct {
+struct test_object{
uint8_t state;
uint32_t buffer[3];
-}test_object_t;
-
-test_object_t test_object;
+};
-Describe(TripleBufferedObject);
-BeforeEach(TripleBufferedObject) {
- triple_buffer_init((triple_buffer_object_t*)&test_object);
-}
-AfterEach(TripleBufferedObject) {}
+test_object test_object;
+class TripleBufferedObject : public testing::Test {
+public:
+ TripleBufferedObject() {
+ triple_buffer_init((triple_buffer_object_t*)&test_object);
+ }
+};
-Ensure(TripleBufferedObject, writes_and_reads_object) {
+TEST_F(TripleBufferedObject, writes_and_reads_object) {
*triple_buffer_begin_write(&test_object) = 0x3456ABCC;
triple_buffer_end_write(&test_object);
- assert_that(*triple_buffer_read(&test_object), is_equal_to(0x3456ABCC));
+ EXPECT_EQ(*triple_buffer_read(&test_object), 0x3456ABCC);
}
-Ensure(TripleBufferedObject, does_not_read_empty) {
- assert_that(triple_buffer_read(&test_object), is_equal_to(NULL));
+TEST_F(TripleBufferedObject, does_not_read_empty) {
+ EXPECT_EQ(triple_buffer_read(&test_object), nullptr);
}
-Ensure(TripleBufferedObject, writes_twice_and_reads_object) {
+TEST_F(TripleBufferedObject, writes_twice_and_reads_object) {
*triple_buffer_begin_write(&test_object) = 0x3456ABCC;
triple_buffer_end_write(&test_object);
*triple_buffer_begin_write(&test_object) = 0x44778899;
triple_buffer_end_write(&test_object);
- assert_that(*triple_buffer_read(&test_object), is_equal_to(0x44778899));
+ EXPECT_EQ(*triple_buffer_read(&test_object), 0x44778899);
}
-Ensure(TripleBufferedObject, performs_another_write_in_the_middle_of_read) {
+TEST_F(TripleBufferedObject, performs_another_write_in_the_middle_of_read) {
*triple_buffer_begin_write(&test_object) = 1;
triple_buffer_end_write(&test_object);
uint32_t* read = triple_buffer_read(&test_object);
*triple_buffer_begin_write(&test_object) = 2;
triple_buffer_end_write(&test_object);
- assert_that(*read, is_equal_to(1));
- assert_that(*triple_buffer_read(&test_object), is_equal_to(2));
- assert_that(triple_buffer_read(&test_object), is_equal_to(NULL));
+ EXPECT_EQ(*read, 1);
+ EXPECT_EQ(*triple_buffer_read(&test_object), 2);
+ EXPECT_EQ(triple_buffer_read(&test_object), nullptr);
}
-Ensure(TripleBufferedObject, performs_two_writes_in_the_middle_of_read) {
+TEST_F(TripleBufferedObject, performs_two_writes_in_the_middle_of_read) {
*triple_buffer_begin_write(&test_object) = 1;
triple_buffer_end_write(&test_object);
uint32_t* read = triple_buffer_read(&test_object);
@@ -76,7 +78,7 @@ Ensure(TripleBufferedObject, performs_two_writes_in_the_middle_of_read) {
triple_buffer_end_write(&test_object);
*triple_buffer_begin_write(&test_object) = 3;
triple_buffer_end_write(&test_object);
- assert_that(*read, is_equal_to(1));
- assert_that(*triple_buffer_read(&test_object), is_equal_to(3));
- assert_that(triple_buffer_read(&test_object), is_equal_to(NULL));
+ EXPECT_EQ(*read, 1);
+ EXPECT_EQ(*triple_buffer_read(&test_object), 3);
+ EXPECT_EQ(triple_buffer_read(&test_object), nullptr);
}
diff --git a/readme.md b/readme.md
index 473fd6a7cf..762c39aa92 100644
--- a/readme.md
+++ b/readme.md
@@ -1137,3 +1137,54 @@ Here is where you can (optionally) define your `KEYMAP` function to remap your m
```
Each of the `kxx` variables needs to be unique, and usually follows the format `k<row><col>`. You can place `KC_NO` where your dead keys are in your matrix.
+
+# Unit Testing
+
+If you are new to unit testing, then you can find many good resources on internet. However most of it is scattered around in small pieces here and there, and there's also many different opinions, so I won't give any recommendations.
+
+Instead I recommend these two books, explaining two different styles of Unit Testing in detail.
+
+* "Test Driven Development: By Example: Kent Beck"
+* "Growing Object-Oriented Software, Guided By Tests: Steve Freeman, Nat Pryce"
+
+If you prefer videos there are Uncle Bob's [Clean Coders Videos](https://cleancoders.com/), which unfortunately cost quite a bit, especially if you want to watch many of them. But James Shore has a free [Let's Play](http://www.jamesshore.com/Blog/Lets-Play) video series.
+
+## Google Test and Google Mock
+It's possible to Unit Test your code using [Google Test](https://github.com/google/googletest). The Google Test framework also includes another component for writing testing mocks and stubs, called "Google Mock". For information how to write the actual tests, please refer to the documentation on that site.
+
+## Use of C++
+
+Note that Google Test and therefore any test has to be written in C++, even if the rest of the QMK codebases is written in C. This should hopefully not be a problem even if you don't know any C++, since there's quite clear documentation and examples of the required C++ features, and you can write the rest of the test code almost as you would write normal C. Note that some compiler errors which you might get can look quite scary, but just read carefully what it says, and you should be ok.
+
+One thing to remember, is that you have to append `extern "C"` around all of your C file includes.
+
+## Adding tests for new or existing features
+
+If you want to unit test some feature, then take a look at the existing serial_link tests, in the `quantum/serial_link/tests folder`, and follow the steps below to create a similar structure.
+
+1. If it doesn't already exist, add a test subfolder to the folder containing the feature.
+2. Create a `testlist.mk` and a `rules.mk` file in that folder.
+3. Include those files from the root folder `testlist.mk`and `build_test.mk` respectively.
+4. Add a new name for your testgroup to the `testlist.mk` file. Each group defined there will be a separate executable. And that's how you can support mocking out different parts. Note that it's worth adding some common prefix, just like it's done for the serial_link tests. The reason for that is that the make command allows substring filtering, so this way you can easily run a subset of the tests.
+5. Define the source files and required options in the `rules.mk` file.
+ * `_SRC` for source files
+ * `_DEFS` for additional defines
+ * `_INC` for additional include folders
+6. Write the tests in a new cpp file inside the test folder you created. That file has to be one of the files included from the `rules.mk` file.
+
+Note how there's several different tests, each mocking out a separate part. Also note that each of them only compiles the very minimum that's needed for the tests. It's recommend that you try to do the same. For a relevant video check out [Matt Hargett "Advanced Unit Testing in C & C++](https://www.youtube.com/watch?v=Wmy6g-aVgZI)
+
+## Running the tests
+
+To run all the tests in the codebase, type `make test`. You can also run test matching a substring by typing `make test-matchingsubstring` Note that the tests are always compiled with the native compiler of your platform, so they are also run like any other program on your computer.
+
+## Debugging the tests
+
+If there are problems with the tests, you can find the executable in the `./build/test` folder. You should be able to run those with GDB or a similar debugger.
+
+## Full Integration tests
+
+It's not yet possible to do a full integration test, where you would compile the whole firmware and define a keymap that you are going to test. However there are plans for doing that, because writing tests that way would probably be easier, at least for people that are not used to unit testing.
+
+In that model you would emulate the input, and expect a certain output from the emulated keyboard.
+
diff --git a/testlist.mk b/testlist.mk
new file mode 100644
index 0000000000..1884d6d3f6
--- /dev/null
+++ b/testlist.mk
@@ -0,0 +1,13 @@
+include $(ROOT_DIR)/quantum/serial_link/tests/testlist.mk
+
+define VALIDATE_TEST_LIST
+ ifneq ($1,)
+ ifeq ($$(findstring -,$1),-)
+ $$(error Test names can't contain '-', but '$1' does)
+ else
+ $$(eval $$(call VALIDATE_TEST_LIST,$$(firstword $2),$$(wordlist 2,9999,$2)))
+ endif
+ endif
+endef
+
+$(eval $(call VALIDATE_TEST_LIST,$(firstword $(TEST_LIST)),$(wordlist 2,9999,$(TEST_LIST)))) \ No newline at end of file
diff --git a/tmk_core/common.mk b/tmk_core/common.mk
index 0b767eb047..f826a7b540 100644
--- a/tmk_core/common.mk
+++ b/tmk_core/common.mk
@@ -5,7 +5,7 @@ else ifeq ($(PLATFORM),CHIBIOS)
PLATFORM_COMMON_DIR = $(COMMON_DIR)/chibios
endif
-SRC += $(COMMON_DIR)/host.c \
+TMK_COMMON_SRC += $(COMMON_DIR)/host.c \
$(COMMON_DIR)/keyboard.c \
$(COMMON_DIR)/action.c \
$(COMMON_DIR)/action_tapping.c \
@@ -21,98 +21,89 @@ SRC += $(COMMON_DIR)/host.c \
$(PLATFORM_COMMON_DIR)/bootloader.c \
ifeq ($(PLATFORM),AVR)
- SRC += $(PLATFORM_COMMON_DIR)/xprintf.S
+ TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/xprintf.S
endif
ifeq ($(PLATFORM),CHIBIOS)
- SRC += $(PLATFORM_COMMON_DIR)/printf.c
- SRC += $(PLATFORM_COMMON_DIR)/eeprom.c
+ TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/printf.c
+ TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/eeprom.c
endif
# Option modules
ifeq ($(strip $(BOOTMAGIC_ENABLE)), yes)
- OPT_DEFS += -DBOOTMAGIC_ENABLE
- SRC += $(COMMON_DIR)/bootmagic.c
+ TMK_COMMON_DEFS += -DBOOTMAGIC_ENABLE
+ TMK_COMMON_SRC += $(COMMON_DIR)/bootmagic.c
else
- OPT_DEFS += -DMAGIC_ENABLE
- SRC += $(COMMON_DIR)/magic.c
+ TMK_COMMON_DEFS += -DMAGIC_ENABLE
+ TMK_COMMON_SRC += $(COMMON_DIR)/magic.c
endif
ifeq ($(strip $(MOUSEKEY_ENABLE)), yes)
- SRC += $(COMMON_DIR)/mousekey.c
- OPT_DEFS += -DMOUSEKEY_ENABLE
- OPT_DEFS += -DMOUSE_ENABLE
+ TMK_COMMON_SRC += $(COMMON_DIR)/mousekey.c
+ TMK_COMMON_DEFS += -DMOUSEKEY_ENABLE
+ TMK_COMMON_DEFS += -DMOUSE_ENABLE
endif
ifeq ($(strip $(EXTRAKEY_ENABLE)), yes)
- OPT_DEFS += -DEXTRAKEY_ENABLE
+ TMK_COMMON_DEFS += -DEXTRAKEY_ENABLE
endif
ifeq ($(strip $(CONSOLE_ENABLE)), yes)
- OPT_DEFS += -DCONSOLE_ENABLE
+ TMK_COMMON_DEFS += -DCONSOLE_ENABLE
else
- OPT_DEFS += -DNO_PRINT
- OPT_DEFS += -DNO_DEBUG
+ TMK_COMMON_DEFS += -DNO_PRINT
+ TMK_COMMON_DEFS += -DNO_DEBUG
endif
ifeq ($(strip $(COMMAND_ENABLE)), yes)
- SRC += $(COMMON_DIR)/command.c
- OPT_DEFS += -DCOMMAND_ENABLE
+ TMK_COMMON_SRC += $(COMMON_DIR)/command.c
+ TMK_COMMON_DEFS += -DCOMMAND_ENABLE
endif
ifeq ($(strip $(NKRO_ENABLE)), yes)
- OPT_DEFS += -DNKRO_ENABLE
+ TMK_COMMON_DEFS += -DNKRO_ENABLE
endif
ifeq ($(strip $(USB_6KRO_ENABLE)), yes)
- OPT_DEFS += -DUSB_6KRO_ENABLE
+ TMK_COMMON_DEFS += -DUSB_6KRO_ENABLE
endif
ifeq ($(strip $(SLEEP_LED_ENABLE)), yes)
- SRC += $(PLATFORM_COMMON_DIR)/sleep_led.c
- OPT_DEFS += -DSLEEP_LED_ENABLE
- OPT_DEFS += -DNO_SUSPEND_POWER_DOWN
+ TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/sleep_led.c
+ TMK_COMMON_DEFS += -DSLEEP_LED_ENABLE
+ TMK_COMMON_DEFS += -DNO_SUSPEND_POWER_DOWN
endif
ifeq ($(strip $(BACKLIGHT_ENABLE)), yes)
- SRC += $(COMMON_DIR)/backlight.c
- OPT_DEFS += -DBACKLIGHT_ENABLE
+ TMK_COMMON_SRC += $(COMMON_DIR)/backlight.c
+ TMK_COMMON_DEFS += -DBACKLIGHT_ENABLE
endif
ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
- OPT_DEFS += -DBLUETOOTH_ENABLE
+ TMK_COMMON_DEFS += -DBLUETOOTH_ENABLE
endif
ifeq ($(strip $(ONEHAND_ENABLE)), yes)
- OPT_DEFS += -DONEHAND_ENABLE
+ TMK_COMMON_DEFS += -DONEHAND_ENABLE
endif
ifeq ($(strip $(KEYMAP_SECTION_ENABLE)), yes)
- OPT_DEFS += -DKEYMAP_SECTION_ENABLE
+ TMK_COMMON_DEFS += -DKEYMAP_SECTION_ENABLE
ifeq ($(strip $(MCU)),atmega32u2)
- EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr35.x
+ TMK_COMMON_LDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr35.x
else ifeq ($(strip $(MCU)),atmega32u4)
- EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr5.x
+ TMK_COMMON_LDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr5.x
else
- EXTRALDFLAGS = $(error no ldscript for keymap section)
+ TMK_COMMON_LDFLAGS = $(error no ldscript for keymap section)
endif
endif
-ifeq ($(MASTER),right)
- OPT_DEFS += -DMASTER_IS_ON_RIGHT
-else
- ifneq ($(MASTER),left)
-$(error MASTER does not have a valid value(left/right))
- endif
-endif
-
-
# Bootloader address
ifdef STM32_BOOTLOADER_ADDRESS
- OPT_DEFS += -DSTM32_BOOTLOADER_ADDRESS=$(STM32_BOOTLOADER_ADDRESS)
+ TMK_COMMON_DEFS += -DSTM32_BOOTLOADER_ADDRESS=$(STM32_BOOTLOADER_ADDRESS)
endif
# Search Path
diff --git a/tmk_core/native.mk b/tmk_core/native.mk
new file mode 100644
index 0000000000..50232ee9b7
--- /dev/null
+++ b/tmk_core/native.mk
@@ -0,0 +1,24 @@
+CC = gcc
+OBJCOPY =
+OBJDUMP =
+SIZE =
+AR =
+NM =
+HEX =
+EEP =
+BIN =
+
+
+COMPILEFLAGS += -funsigned-char
+COMPILEFLAGS += -funsigned-bitfields
+COMPILEFLAGS += -ffunction-sections
+COMPILEFLAGS += -fdata-sections
+COMPILEFLAGS += -fshort-enums
+
+CFLAGS += $(COMPILEFLAGS)
+CFLAGS += -fno-inline-small-functions
+CFLAGS += -fno-strict-aliasing
+
+CPPFLAGS += $(COMPILEFLAGS)
+CPPFLAGS += -fno-exceptions
+CPPFLAGS += -std=gnu++11 \ No newline at end of file
diff --git a/tmk_core/rules.mk b/tmk_core/rules.mk
index 21011c2808..79fc7119a6 100644
--- a/tmk_core/rules.mk
+++ b/tmk_core/rules.mk
@@ -21,13 +21,14 @@ VPATH_SRC := $(VPATH)
vpath %.c $(VPATH_SRC)
vpath %.h $(VPATH_SRC)
vpath %.cpp $(VPATH_SRC)
+vpath %.cc $(VPATH_SRC)
vpath %.hpp $(VPATH_SRC)
vpath %.S $(VPATH_SRC)
VPATH :=
# Convert all SRC to OBJ
define OBJ_FROM_SRC
-$(patsubst %.c,$1/%.o,$(patsubst %.cpp,$1/%.o,$(patsubst %.S,$1/%.o,$($1_SRC))))
+$(patsubst %.c,$1/%.o,$(patsubst %.cpp,$1/%.o,$(patsubst %.cc,$1/%.o,$(patsubst %.S,$1/%.o,$($1_SRC)))))
endef
$(foreach OUTPUT,$(OUTPUTS),$(eval $(OUTPUT)_OBJ +=$(call OBJ_FROM_SRC,$(OUTPUT))))
@@ -160,6 +161,7 @@ SCANF_LIB =
MATH_LIB = -lm
+CREATE_MAP ?= yes
#---------------- Linker Options ----------------
@@ -170,7 +172,10 @@ MATH_LIB = -lm
# Comennt out "--relax" option to avoid a error such:
# (.vectors+0x30): relocation truncated to fit: R_AVR_13_PCREL against symbol `__vector_12'
#
-LDFLAGS += -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref
+
+ifeq ($(CREATE_MAP),yes)
+ LDFLAGS += -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref
+endif
#LDFLAGS += -Wl,--relax
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
@@ -202,14 +207,6 @@ ALL_ASFLAGS = $(MCUFLAGS) -x assembler-with-cpp $(ASFLAGS) $(EXTRAFLAGS)
MOVE_DEP = mv -f $(patsubst %.o,%.td,$@) $(patsubst %.o,%.d,$@)
-# Default target.
-all: build sizeafter
-
-# Change the build target to build a HEX file or a library.
-build: elf hex
-#build: elf hex eep lss sym
-#build: lib
-
elf: $(BUILD_DIR)/$(TARGET).elf
hex: $(BUILD_DIR)/$(TARGET).hex
@@ -305,7 +302,13 @@ $1/%.o : %.cpp $1/%.d $1/cppflags.txt $1/compiler.txt | $(BEGIN)
@mkdir -p $$(@D)
@$$(SILENT) || printf "$$(MSG_COMPILING_CPP) $$<" | $$(AWK_CMD)
$$(eval CMD=$$(CC) -c $$($1_CPPFLAGS) $$(GENDEPFLAGS) $$< -o $$@ && $$(MOVE_DEP))
- @$(BUILD_CMD)
+ @$$(BUILD_CMD)
+
+$1/%.o : %.cc $1/%.d $1/cppflags.txt $1/compiler.txt | $(BEGIN)
+ @mkdir -p $$(@D)
+ @$$(SILENT) || printf "$$(MSG_COMPILING_CPP) $$<" | $$(AWK_CMD)
+ $$(eval CMD=$$(CC) -c $$($1_CPPFLAGS) $$(GENDEPFLAGS) $$< -o $$@ && $$(MOVE_DEP))
+ @$$(BUILD_CMD)
# Assemble: create object files from assembler source files.
$1/%.o : %.S $1/asflags.txt $1/compiler.txt | $(BEGIN)
@@ -361,10 +364,10 @@ show_path:
@echo OBJ=$(OBJ)
# Create build directory
-$(shell mkdir $(BUILD_DIR) 2>/dev/null)
+$(shell mkdir -p $(BUILD_DIR) 2>/dev/null)
# Create object files directory
-$(eval $(foreach OUTPUT,$(OUTPUTS),$(shell mkdir $(OUTPUT) 2>/dev/null)))
+$(eval $(foreach OUTPUT,$(OUTPUTS),$(shell mkdir -p $(OUTPUT) 2>/dev/null)))
# Include the dependency files.
-include $(patsubst %.o,%.d,$(OBJ))