diff --git a/README.md b/README.md index 6a60860..8a57f1d 100644 --- a/README.md +++ b/README.md @@ -28,3 +28,17 @@ There's also a set of [pyjam](https://github.com/kaspar030/pyjam) buildfiles. If you've got pyjam installed, use them like this: # pyj -a + +## Unit tests + +Unit tests are provided by reuse of the Embedded Unit framework in the RIOT submodule. +First, compile the framework. + + # cd tests/embunit + # make + +Then, make and run the unit tests as required. + + # cd .. + # make + # ./tests \ No newline at end of file diff --git a/nanocoap/Makefile b/nanocoap/Makefile index 25a4ca5..85b8b5d 100644 --- a/nanocoap/Makefile +++ b/nanocoap/Makefile @@ -8,6 +8,7 @@ CFLAGS += -DSOCK_HAS_IPV4 -DSOCK_HAS_IPV6 -DLINUX -D_DEFAULT_SOURCE SHARED_SRC=nanocoap.c handler.c nanocoap_sock.c ../src/util.c ../src/posix/posix.c CLIENT_SRC=client.c nanocoap_sock.c $(SHARED_SRC) SERVER_SRC=server.c $(SHARED_SRC) +OBJS=bin/nanocoap.o bin/handler.o bin/: @mkdir -p bin @@ -18,5 +19,11 @@ bin/nanocoap_client: $(CLIENT_SRC) | bin/ bin/nanocoap_server: $(SERVER_SRC) | bin/ $(CC) $(CFLAGS) $^ -o $@ +# Used by unit tests +objs: $(OBJS) + +%.o: %.c + $(CC) $(CFLAGS) -c $^ + clean: - rm -f bin/nanocoap_client bin/nanocoap_server + rm -f bin/nanocoap_client bin/nanocoap_server bin/*.obj diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..39a39e7 --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1,3 @@ +*.o +tests +embunit/*.a diff --git a/tests/AllTests.c b/tests/AllTests.c new file mode 100644 index 0000000..c95a7f6 --- /dev/null +++ b/tests/AllTests.c @@ -0,0 +1,11 @@ +#include + +TestRef NanocoapTest_tests(void); + +int main (int argc, const char* argv[]) +{ + TestRunner_start(); + TestRunner_runTest(NanocoapTest_tests()); + TestRunner_end(); + return 0; +} diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000..d602f67 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,28 @@ +CC = gcc +CFLAGS = -O +INCLUDES = -I.. -I../riot/sys/embunit -I../riot/sys/include +LIBS = embunit +RM = rm +TARGET = tests +NANO_DIR = ../nanocoap/bin +NANO_OBJS = $(NANO_DIR)/nanocoap.o $(NANO_DIR)/handler.o +OBJS = AllTests.o nanocoapTest.o +RIOTBASE = $(CURDIR)/../riot + +all: $(TARGET) + +$(TARGET): nano_objs $(OBJS) + $(CC) -o $@ $(OBJS) $(NANO_OBJS) -L$(LIBS) -lembUnit + +.c.o: + $(CC) \ + -DRIOT_FILE_RELATIVE=\"$(patsubst $(RIOTBASE)/%,%,$(abspath $<))\" \ + $(CFLAGS) $(INCLUDES) -c $< + +nano_objs: + -@cd ../nanocoap;$(MAKE) objs + +clean: + -$(RM) -f $(TARGET) $(OBJS) + +.PHONY: clean all nano_objs diff --git a/tests/embunit/Makefile b/tests/embunit/Makefile new file mode 100644 index 0000000..99d9152 --- /dev/null +++ b/tests/embunit/Makefile @@ -0,0 +1,9 @@ +all: + $(MAKE) -f Makefile.embunit + $(MAKE) -f Makefile.textui + +clean: + $(MAKE) -f Makefile.embunit clean + $(MAKE) -f Makefile.textui clean + +.PHONY: clean all diff --git a/tests/embunit/Makefile.embunit b/tests/embunit/Makefile.embunit new file mode 100644 index 0000000..83037f9 --- /dev/null +++ b/tests/embunit/Makefile.embunit @@ -0,0 +1,25 @@ +CC = gcc +CFLAGS = -O +AR = ar +ARFLAGS = ru +RANLIB = ranlib +RM = rm +SRC = ../../riot/sys/embunit +INCLUDES = -I../../riot/sys/embunit -I../../riot/sys/include/embUnit +OUTPUT = ./ +TARGET = libembUnit.a +OBJS = AssertImpl.o RepeatedTest.o stdImpl.o TestCaller.o TestCase.o TestResult.o TestRunner.o TestSuite.o + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(AR) $(ARFLAGS) $(OUTPUT)$@ $(OBJS) + $(RANLIB) $(OUTPUT)$@ + +%.o: $(SRC)/%.c + $(CC) $(CFLAGS) $(INCLUDES) -c $< + +clean: + -$(RM) $(OBJS) $(TARGET) + +.PHONY: clean all diff --git a/tests/embunit/Makefile.textui b/tests/embunit/Makefile.textui new file mode 100644 index 0000000..a41bc01 --- /dev/null +++ b/tests/embunit/Makefile.textui @@ -0,0 +1,27 @@ +CC = gcc +CFLAGS = -O +INCLUDES = .. +LIBS = ../lib +AR = ar +ARFLAGS = ru +RANLIB = ranlib +RM = rm +SRC = ../../riot/sys/embunit +INCLUDES = -I../../riot/sys/embunit -I../../riot/sys/include/embUnit -I../../riot/sys/include +OUTPUT = ./ +TARGET = libtextui.a +OBJS = TextUIRunner.o XMLOutputter.o TextOutputter.o CompilerOutputter.o + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(AR) $(ARFLAGS) $(OUTPUT)$@ $(OBJS) + $(RANLIB) $(OUTPUT)$@ + +%.o: $(SRC)/%.c + $(CC) $(CFLAGS) -I$(INCLUDES) -c $< + +clean: + -$(RM) $(TARGET) $(OBJS) + +.PHONY: clean all diff --git a/tests/nanocoapTest.c b/tests/nanocoapTest.c new file mode 100644 index 0000000..d73b675 --- /dev/null +++ b/tests/nanocoapTest.c @@ -0,0 +1,59 @@ +#include +#include "nanocoap/nanocoap.h" + +/* + * Parses a basic NON GET request for '/cli/stats'. Includes a 2-byte token. + */ +static void testParseGetReq(void) +{ + coap_pkt_t pdu; + + uint8_t buf[] = { + 0x52, 0x01, 0xd3, 0x06, 0x35, 0x61, 0xb3, 0x63, + 0x6c, 0x69, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73 + }; + + int res = coap_parse(&pdu, &buf[0], sizeof(buf)); + + TEST_ASSERT_EQUAL_INT(0, res); + TEST_ASSERT_EQUAL_INT(COAP_METHOD_GET, coap_get_code(&pdu)); + TEST_ASSERT_EQUAL_INT(2, coap_get_token_len(&pdu)); + TEST_ASSERT_EQUAL_INT(4 + 2, coap_get_total_hdr_len(&pdu)); + TEST_ASSERT_EQUAL_INT(COAP_TYPE_NON, coap_get_type(&pdu)); + TEST_ASSERT_EQUAL_INT(0, pdu.payload_len); + TEST_ASSERT_EQUAL_STRING("/cli/stats", (char *) &pdu.url[0]); +} + +/* + * Extends testParseGetReq to include Observe registration. + */ +static void testParseObserveReq(void) +{ + coap_pkt_t pdu; + + uint8_t buf[] = { + 0x52, 0x01, 0xd3, 0x06, 0x35, 0x61, 0x60, 0x53, + 0x63, 0x6c, 0x69, 0x05, 0x73, 0x74, 0x61, 0x74, + 0x73 + }; + + int res = coap_parse(&pdu, &buf[0], sizeof(buf)); + + TEST_ASSERT_EQUAL_INT(0, res); + TEST_ASSERT(coap_has_observe(&pdu)); + TEST_ASSERT_EQUAL_INT(0, coap_get_observe(&pdu)); + TEST_ASSERT_EQUAL_INT(0, pdu.payload_len); + /* indicates other options OK */ + TEST_ASSERT_EQUAL_STRING("/cli/stats", (char *) &pdu.url[0]); +} + +TestRef NanocoapTest_tests(void) +{ + EMB_UNIT_TESTFIXTURES(fixtures) { + new_TestFixture(testParseGetReq), + new_TestFixture(testParseObserveReq), + }; + EMB_UNIT_TESTCALLER(NanocoapTest, NULL, NULL, fixtures); + + return (TestRef)&NanocoapTest; +}