aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-06-04 18:27:40 +0200
committerLoek Le Blansch <loek@pipeframe.xyz>2024-06-04 18:27:40 +0200
commit078c6661c24a9460240d9c7c063a44e9bed6f96a (patch)
tree4d19d628210d5e0414228f1330c0d998b44c02e8
parent18d06c79b9f6a625eb218a15c8216556fb99dc02 (diff)
add i2ctcp unit tests
-rw-r--r--client/makefile2
-rw-r--r--i2ctcp/i2ctcpv1.c41
-rw-r--r--shared/pb/moddrv.c21
-rw-r--r--shared/pb/moddrv.h2
-rw-r--r--test/CMakeLists.txt27
-rw-r--r--test/ExampleTest.cpp5
-rw-r--r--test/i2ctcp/main.cpp46
-rw-r--r--test/makefile7
8 files changed, 94 insertions, 57 deletions
diff --git a/client/makefile b/client/makefile
index 8352615..5cbf045 100644
--- a/client/makefile
+++ b/client/makefile
@@ -1,2 +1,4 @@
+TARGET = $(BUILD_DIR)/pbc
+
include ../lazy.mk
diff --git a/i2ctcp/i2ctcpv1.c b/i2ctcp/i2ctcpv1.c
index b406d8d..2231038 100644
--- a/i2ctcp/i2ctcpv1.c
+++ b/i2ctcp/i2ctcpv1.c
@@ -7,38 +7,31 @@
#include "i2ctcpv1.h"
int i2ctcp_read(i2ctcp_msg_t * target, const char * buf, size_t buf_sz) {
+ mpack_reader_t reader;
+ mpack_reader_init_data(&reader, buf, buf_sz);
+
// at start of message
if (target->_rdata == 0) {
- // NOTE: The entire start of a message needs to be readable from the buffer
- // at this point. When target->addr can be read and target->length is past
- // the end of the current buffer block, this function will crash and burn.
- // This is a highly unlikely scenario, as i2ctcp_read is called for each
- // chunk of a TCP frame, and frames (should) include only one puzzle bus
- // message. The check here is kind of optional.
- if (buf_sz < 4) return -1;
-
- // mpack reader is used for the first buffer block, as it contains the data
- // size info
- mpack_reader_t reader;
- mpack_reader_init_data(&reader, buf, buf_sz);
-
target->addr = mpack_expect_u16(&reader);
target->length = target->_rdata = mpack_expect_bin(&reader);
+ if (mpack_reader_error(&reader) != mpack_ok) return -1;
target->data = (char *) malloc(target->length);
- // read remaining data in (header) packet
- size_t to_read = mpack_reader_remaining(&reader, NULL);
- mpack_read_bytes(&reader, target->data, to_read);
- target->_rdata -= to_read;
- } else {
- // continue reading chunks of target->data until the amount of bytes
- // specified in target->length
- size_t to_read = MIN(buf_sz, target->_rdata);
- char * data = target->data + target->length - target->_rdata;
- memcpy(data, buf, to_read);
- target->_rdata -= to_read;
+ // seek forward in buf to where binary data begins (to avoid having to read
+ // from private member reader.data in the memcpy below)
+ buf += buf_sz - mpack_reader_remaining(&reader, NULL);
}
+ // continue reading chunks of target->data until the amount of bytes
+ // specified in target->length
+ size_t to_read = MIN(mpack_reader_remaining(&reader, NULL), target->_rdata);
+ char * data = target->data + target->length - target->_rdata;
+ memcpy(data, buf, to_read);
+ target->_rdata -= to_read;
+ // NOTE: memcpy is used here because mpack_read_bytes requires that a tag was
+ // opened, which is not the case for the chunks following the initial mpack
+ // header
+
// if rdata = 0, the message was completely read
return target->_rdata;
}
diff --git a/shared/pb/moddrv.c b/shared/pb/moddrv.c
index 1f7fab8..9677341 100644
--- a/shared/pb/moddrv.c
+++ b/shared/pb/moddrv.c
@@ -17,25 +17,8 @@ __weak void pbdrv_hook_mod_state_write(enum pb_state state) {
_global_state = state;
}
-__weak void pbdrv_i2c_recv(uint16_t i2c_addr, const char * buf, size_t sz) {
- if (sz == 0) return;
- enum pb_cmd cmd = (enum pb_cmd) buf[0];
-
- // shift buffer pointer to only contain the puzzle bus message buf
- buf++;
- sz--;
-
- // allow user to implement custom commands
- if (pbdrv_hook_cmd(i2c_addr, cmd, buf, sz))
- return;
-
- switch (cmd) {
- case PB_CMD_READ: return pbdrv_handle_read(i2c_addr, buf, sz);
- case PB_CMD_WRITE: return pbdrv_handle_write(i2c_addr, buf, sz);
- case PB_CMD_MAGIC: return pbdrv_handle_magic(i2c_addr, buf, sz);
- case PB_CMD_SEX: return pbdrv_handle_sex(i2c_addr, buf, sz);
- default: return;
- }
+__weak void pbdrv_i2c_recv(const char * buf, size_t sz) {
+ return;
}
__weak void pbdrv_handle_read(uint16_t i2c_addr, const char * buf, size_t sz) {
diff --git a/shared/pb/moddrv.h b/shared/pb/moddrv.h
index ecfc13a..d2e2d97 100644
--- a/shared/pb/moddrv.h
+++ b/shared/pb/moddrv.h
@@ -24,7 +24,7 @@
extern "C" {
#endif
-void pbdrv_i2c_recv(uint16_t i2c_addr, const char * buf, size_t sz);
+void pbdrv_i2c_recv(const char * buf, size_t sz);
void pbdrv_i2c_send(uint16_t i2c_addr, const char * buf, size_t sz);
enum pb_state pbdrv_hook_mod_state_read();
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index a280a86..44191cc 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,23 +1,26 @@
cmake_minimum_required(VERSION 3.29)
-project(puzzlebox_test C CXX ASM)
-
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
-add_executable(tests
- ExampleTest.cpp
-)
+project(pbtest C CXX ASM)
-enable_testing()
+include(../i2ctcp/include.cmake)
+include(../shared/include.cmake)
+
+add_executable(test
+ ExampleTest.cpp
+ i2ctcp/main.cpp
+ )
+# enable_testing()
add_subdirectory(lib/googletest)
-target_include_directories(tests PRIVATE ${CMAKE_CURRENT_LIST_DIR})
-target_link_libraries(tests PRIVATE gtest_main)
+# target_include_directories(tests PRIVATE ${CMAKE_CURRENT_LIST_DIR})
+target_link_libraries(test
+ gtest_main
+ i2ctcp
+ mpack
+ )
-add_test(
- NAME tests
- COMMAND tests
-)
diff --git a/test/ExampleTest.cpp b/test/ExampleTest.cpp
index a3909f5..3da58ff 100644
--- a/test/ExampleTest.cpp
+++ b/test/ExampleTest.cpp
@@ -4,4 +4,7 @@ class ExampleTest : public testing::Test {
protected:
};
-TEST_F(ExampleTest, Test) { EXPECT_EQ(5, 5); } \ No newline at end of file
+TEST_F(ExampleTest, Test) {
+ EXPECT_EQ(5, 5);
+}
+
diff --git a/test/i2ctcp/main.cpp b/test/i2ctcp/main.cpp
new file mode 100644
index 0000000..1f0c3ff
--- /dev/null
+++ b/test/i2ctcp/main.cpp
@@ -0,0 +1,46 @@
+#include <algorithm>
+#include <gtest/gtest.h>
+
+#include "i2ctcpv1.h"
+
+using std::min;
+
+const uint8_t data[] = { 0xff, 0x00, 0xde, 0xad, 0xbe, 0xef, };
+const size_t data_len = sizeof(data);
+const size_t chunk_size = 6;
+
+char * send_data = nullptr;
+size_t send_size = 0;
+
+TEST(i2ctcp, send) {
+ i2ctcp_msg_t send_msg = {
+ .addr = 0x1122,
+ .data = (char *) data,
+ .length = data_len,
+ };
+
+ ASSERT_TRUE(i2ctcp_write(&send_msg, &send_data, &send_size));
+ ASSERT_NE(send_data, nullptr);
+ ASSERT_GE(send_size, 0);
+}
+
+TEST(i2ctcp, recv) {
+ i2ctcp_msg_t recv_msg;
+ i2ctcp_read_reset(&recv_msg);
+ for (size_t i = 0; i < send_size; i += chunk_size) {
+ size_t expected_size = min(send_size, i + chunk_size) - i;
+
+ int parsed = i2ctcp_read(&recv_msg, send_data + i, expected_size);
+ EXPECT_GE(parsed, 0);
+
+ if (i + expected_size == send_size)
+ EXPECT_EQ(parsed, 0);
+ else
+ EXPECT_GT(parsed, 0);
+ }
+
+ ASSERT_NE(recv_msg.data, nullptr);
+ ASSERT_EQ(recv_msg.length, data_len);
+ ASSERT_EQ(0, memcmp(recv_msg.data, data, data_len));
+}
+
diff --git a/test/makefile b/test/makefile
new file mode 100644
index 0000000..7aeee34
--- /dev/null
+++ b/test/makefile
@@ -0,0 +1,7 @@
+TARGET = $(BUILD_DIR)/test
+
+include ../lazy.mk
+
+test: $(TARGET) FORCE
+ $(TARGET)
+