From bcdf9ab76bf3723e6015d4255d53e7c1e7259b61 Mon Sep 17 00:00:00 2001
From: Fred Sundvik <fsundvik@gmail.com>
Date: Sat, 27 Aug 2016 14:18:49 +0300
Subject: [PATCH] Convert transport_tests to GTest

---
 quantum/serial_link/protocol/transport.c      |   4 +
 quantum/serial_link/protocol/transport.h      |   7 +-
 quantum/serial_link/tests/rules.mk            |   7 +-
 quantum/serial_link/tests/transport_tests.c   | 168 ----------------
 quantum/serial_link/tests/transport_tests.cpp | 188 ++++++++++++++++++
 5 files changed, 202 insertions(+), 172 deletions(-)
 delete mode 100644 quantum/serial_link/tests/transport_tests.c
 create mode 100644 quantum/serial_link/tests/transport_tests.cpp

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/rules.mk b/quantum/serial_link/tests/rules.mk
index 7f2a8f457c..bf342c9d26 100644
--- a/quantum/serial_link/tests/rules.mk
+++ b/quantum/serial_link/tests/rules.mk
@@ -10,4 +10,9 @@ serial_link_frame_router_SRC := \
 
 serial_link_frame_validator_SRC := \
 	$(SERIAL_PATH)/tests/frame_validator_tests.cpp \
-	$(SERIAL_PATH)/protocol/frame_validator.c 
\ No newline at end of file
+	$(SERIAL_PATH)/protocol/frame_validator.c 
+
+serial_link_transport_SRC := \
+	$(SERIAL_PATH)/tests/transport_tests.cpp \
+	$(SERIAL_PATH)/protocol/transport.c \
+	$(SERIAL_PATH)/protocol/triple_buffered_object.c 
\ 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);
+}