aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFred Sundvik <fsundvik@gmail.com>2016-08-27 14:18:49 +0300
committerFred Sundvik <fsundvik@gmail.com>2016-08-27 21:57:49 +0300
commitbcdf9ab76bf3723e6015d4255d53e7c1e7259b61 (patch)
tree90bdb182315b96740da331c3d76c20187bef1f6f
parentb3eba797af74ace19b9f2e762bdd33d9449e3f94 (diff)
downloadqmk_firmware-bcdf9ab76bf3723e6015d4255d53e7c1e7259b61.tar.gz
qmk_firmware-bcdf9ab76bf3723e6015d4255d53e7c1e7259b61.zip
Convert transport_tests to GTest
-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/rules.mk7
-rw-r--r--quantum/serial_link/tests/transport_tests.c168
-rw-r--r--quantum/serial_link/tests/transport_tests.cpp188
5 files changed, 202 insertions, 172 deletions
diff --git a/quantum/serial_link/protocol/transport.c b/quantum/serial_link/protocol/transport.c
index f418d11ce..ff795fe20 100644
--- a/quantum/serial_link/protocol/transport.c
+++ b/quantum/serial_link/protocol/transport.c
@@ -31,6 +31,10 @@ SOFTWARE.
31static remote_object_t* remote_objects[MAX_REMOTE_OBJECTS]; 31static remote_object_t* remote_objects[MAX_REMOTE_OBJECTS];
32static uint32_t num_remote_objects = 0; 32static uint32_t num_remote_objects = 0;
33 33
34void reinitialize_serial_link_transport(void) {
35 num_remote_objects = 0;
36}
37
34void add_remote_objects(remote_object_t** _remote_objects, uint32_t _num_remote_objects) { 38void add_remote_objects(remote_object_t** _remote_objects, uint32_t _num_remote_objects) {
35 unsigned int i; 39 unsigned int i;
36 for(i=0;i<_num_remote_objects;i++) { 40 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 9a052d880..2c5d890b2 100644
--- a/quantum/serial_link/protocol/transport.h
+++ b/quantum/serial_link/protocol/transport.h
@@ -82,7 +82,7 @@ typedef struct { \
82 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ 82 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
83 uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);\ 83 uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);\
84 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \ 84 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
85 return triple_buffer_read_internal(obj->object_size, tb); \ 85 return (type*)triple_buffer_read_internal(obj->object_size, tb); \
86 } 86 }
87 87
88#define MASTER_TO_SINGLE_SLAVE_OBJECT(name, type) \ 88#define MASTER_TO_SINGLE_SLAVE_OBJECT(name, type) \
@@ -112,7 +112,7 @@ typedef struct { \
112 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \ 112 remote_object_t* obj = (remote_object_t*)&remote_object_##name; \
113 uint8_t* start = obj->buffer + NUM_SLAVES * LOCAL_OBJECT_SIZE(obj->object_size);\ 113 uint8_t* start = obj->buffer + NUM_SLAVES * LOCAL_OBJECT_SIZE(obj->object_size);\
114 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \ 114 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
115 return triple_buffer_read_internal(obj->object_size, tb); \ 115 return (type*)triple_buffer_read_internal(obj->object_size, tb); \
116 } 116 }
117 117
118#define SLAVE_TO_MASTER_OBJECT(name, type) \ 118#define SLAVE_TO_MASTER_OBJECT(name, type) \
@@ -139,12 +139,13 @@ typedef struct { \
139 uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);\ 139 uint8_t* start = obj->buffer + LOCAL_OBJECT_SIZE(obj->object_size);\
140 start+=slave * REMOTE_OBJECT_SIZE(obj->object_size); \ 140 start+=slave * REMOTE_OBJECT_SIZE(obj->object_size); \
141 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \ 141 triple_buffer_object_t* tb = (triple_buffer_object_t*)start; \
142 return triple_buffer_read_internal(obj->object_size, tb); \ 142 return (type*)triple_buffer_read_internal(obj->object_size, tb); \
143 } 143 }
144 144
145#define REMOTE_OBJECT(name) (remote_object_t*)&remote_object_##name 145#define REMOTE_OBJECT(name) (remote_object_t*)&remote_object_##name
146 146
147void add_remote_objects(remote_object_t** remote_objects, uint32_t num_remote_objects); 147void add_remote_objects(remote_object_t** remote_objects, uint32_t num_remote_objects);
148void reinitialize_serial_link_transport(void);
148void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size); 149void transport_recv_frame(uint8_t from, uint8_t* data, uint16_t size);
149void update_transport(void); 150void update_transport(void);
150 151
diff --git a/quantum/serial_link/tests/rules.mk b/quantum/serial_link/tests/rules.mk
index 7f2a8f457..bf342c9d2 100644
--- a/quantum/serial_link/tests/rules.mk
+++ b/quantum/serial_link/tests/rules.mk
@@ -10,4 +10,9 @@ serial_link_frame_router_SRC := \
10 10
11serial_link_frame_validator_SRC := \ 11serial_link_frame_validator_SRC := \
12 $(SERIAL_PATH)/tests/frame_validator_tests.cpp \ 12 $(SERIAL_PATH)/tests/frame_validator_tests.cpp \
13 $(SERIAL_PATH)/protocol/frame_validator.c \ No newline at end of file 13 $(SERIAL_PATH)/protocol/frame_validator.c
14
15serial_link_transport_SRC := \
16 $(SERIAL_PATH)/tests/transport_tests.cpp \
17 $(SERIAL_PATH)/protocol/transport.c \
18 $(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 358e1b9fd..000000000
--- a/quantum/serial_link/tests/transport_tests.c
+++ /dev/null
@@ -1,168 +0,0 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include <cgreen/cgreen.h>
26#include <cgreen/mocks.h>
27#include "serial_link/protocol/transport.c"
28#include "serial_link/protocol/triple_buffered_object.c"
29
30void signal_data_written(void) {
31 mock();
32}
33
34static uint8_t sent_data[2048];
35static uint16_t sent_data_size;
36
37void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) {
38 mock(destination);
39 memcpy(sent_data + sent_data_size, data, size);
40 sent_data_size += size;
41}
42
43typedef struct {
44 uint32_t test;
45} test_object1_t;
46
47typedef struct {
48 uint32_t test1;
49 uint32_t test2;
50} test_object2_t;
51
52MASTER_TO_ALL_SLAVES_OBJECT(master_to_slave, test_object1_t);
53MASTER_TO_SINGLE_SLAVE_OBJECT(master_to_single_slave, test_object1_t);
54SLAVE_TO_MASTER_OBJECT(slave_to_master, test_object1_t);
55
56static remote_object_t* test_remote_objects[] = {
57 REMOTE_OBJECT(master_to_slave),
58 REMOTE_OBJECT(master_to_single_slave),
59 REMOTE_OBJECT(slave_to_master),
60};
61
62Describe(Transport);
63BeforeEach(Transport) {
64 add_remote_objects(test_remote_objects, sizeof(test_remote_objects) / sizeof(remote_object_t*));
65 sent_data_size = 0;
66}
67AfterEach(Transport) {}
68
69Ensure(Transport, write_to_local_signals_an_event) {
70 begin_write_master_to_slave();
71 expect(signal_data_written);
72 end_write_master_to_slave();
73 begin_write_slave_to_master();
74 expect(signal_data_written);
75 end_write_slave_to_master();
76 begin_write_master_to_single_slave(1);
77 expect(signal_data_written);
78 end_write_master_to_single_slave(1);
79}
80
81Ensure(Transport, writes_from_master_to_all_slaves) {
82 update_transport();
83 test_object1_t* obj = begin_write_master_to_slave();
84 obj->test = 5;
85 expect(signal_data_written);
86 end_write_master_to_slave();
87 expect(router_send_frame,
88 when(destination, is_equal_to(0xFF)));
89 update_transport();
90 transport_recv_frame(0, sent_data, sent_data_size);
91 test_object1_t* obj2 = read_master_to_slave();
92 assert_that(obj2, is_not_equal_to(NULL));
93 assert_that(obj2->test, is_equal_to(5));
94}
95
96Ensure(Transport, writes_from_slave_to_master) {
97 update_transport();
98 test_object1_t* obj = begin_write_slave_to_master();
99 obj->test = 7;
100 expect(signal_data_written);
101 end_write_slave_to_master();
102 expect(router_send_frame,
103 when(destination, is_equal_to(0)));
104 update_transport();
105 transport_recv_frame(3, sent_data, sent_data_size);
106 test_object1_t* obj2 = read_slave_to_master(2);
107 assert_that(read_slave_to_master(0), is_equal_to(NULL));
108 assert_that(obj2, is_not_equal_to(NULL));
109 assert_that(obj2->test, is_equal_to(7));
110}
111
112Ensure(Transport, writes_from_master_to_single_slave) {
113 update_transport();
114 test_object1_t* obj = begin_write_master_to_single_slave(3);
115 obj->test = 7;
116 expect(signal_data_written);
117 end_write_master_to_single_slave(3);
118 expect(router_send_frame,
119 when(destination, is_equal_to(4)));
120 update_transport();
121 transport_recv_frame(0, sent_data, sent_data_size);
122 test_object1_t* obj2 = read_master_to_single_slave();
123 assert_that(obj2, is_not_equal_to(NULL));
124 assert_that(obj2->test, is_equal_to(7));
125}
126
127Ensure(Transport, ignores_object_with_invalid_id) {
128 update_transport();
129 test_object1_t* obj = begin_write_master_to_single_slave(3);
130 obj->test = 7;
131 expect(signal_data_written);
132 end_write_master_to_single_slave(3);
133 expect(router_send_frame,
134 when(destination, is_equal_to(4)));
135 update_transport();
136 sent_data[sent_data_size - 1] = 44;
137 transport_recv_frame(0, sent_data, sent_data_size);
138 test_object1_t* obj2 = read_master_to_single_slave();
139 assert_that(obj2, is_equal_to(NULL));
140}
141
142Ensure(Transport, ignores_object_with_size_too_small) {
143 update_transport();
144 test_object1_t* obj = begin_write_master_to_slave();
145 obj->test = 7;
146 expect(signal_data_written);
147 end_write_master_to_slave();
148 expect(router_send_frame);
149 update_transport();
150 sent_data[sent_data_size - 2] = 0;
151 transport_recv_frame(0, sent_data, sent_data_size - 1);
152 test_object1_t* obj2 = read_master_to_slave();
153 assert_that(obj2, is_equal_to(NULL));
154}
155
156Ensure(Transport, ignores_object_with_size_too_big) {
157 update_transport();
158 test_object1_t* obj = begin_write_master_to_slave();
159 obj->test = 7;
160 expect(signal_data_written);
161 end_write_master_to_slave();
162 expect(router_send_frame);
163 update_transport();
164 sent_data[sent_data_size + 21] = 0;
165 transport_recv_frame(0, sent_data, sent_data_size + 22);
166 test_object1_t* obj2 = read_master_to_slave();
167 assert_that(obj2, is_equal_to(NULL));
168}
diff --git a/quantum/serial_link/tests/transport_tests.cpp b/quantum/serial_link/tests/transport_tests.cpp
new file mode 100644
index 000000000..21b7b165f
--- /dev/null
+++ b/quantum/serial_link/tests/transport_tests.cpp
@@ -0,0 +1,188 @@
1/*
2The MIT License (MIT)
3
4Copyright (c) 2016 Fred Sundvik
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#include "gtest/gtest.h"
26#include "gmock/gmock.h"
27
28using testing::_;
29using testing::ElementsAreArray;
30using testing::Args;
31
32extern "C" {
33#include "serial_link/protocol/transport.h"
34}
35
36struct test_object1 {
37 uint32_t test;
38};
39
40struct test_object2 {
41 uint32_t test1;
42 uint32_t test2;
43};
44
45MASTER_TO_ALL_SLAVES_OBJECT(master_to_slave, test_object1);
46MASTER_TO_SINGLE_SLAVE_OBJECT(master_to_single_slave, test_object1);
47SLAVE_TO_MASTER_OBJECT(slave_to_master, test_object1);
48
49static remote_object_t* test_remote_objects[] = {
50 REMOTE_OBJECT(master_to_slave),
51 REMOTE_OBJECT(master_to_single_slave),
52 REMOTE_OBJECT(slave_to_master),
53};
54
55class Transport : public testing::Test {
56public:
57 Transport() {
58 Instance = this;
59 add_remote_objects(test_remote_objects, sizeof(test_remote_objects) / sizeof(remote_object_t*));
60 }
61
62 ~Transport() {
63 Instance = nullptr;
64 reinitialize_serial_link_transport();
65 }
66
67 MOCK_METHOD0(signal_data_written, void ());
68 MOCK_METHOD1(router_send_frame, void (uint8_t destination));
69
70 void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) {
71 router_send_frame(destination);
72 std::copy(data, data + size, std::back_inserter(sent_data));
73 }
74
75 static Transport* Instance;
76
77 std::vector<uint8_t> sent_data;
78};
79
80Transport* Transport::Instance = nullptr;
81
82extern "C" {
83void signal_data_written(void) {
84 Transport::Instance->signal_data_written();
85}
86
87void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) {
88 Transport::Instance->router_send_frame(destination, data, size);
89}
90}
91
92TEST_F(Transport, write_to_local_signals_an_event) {
93 begin_write_master_to_slave();
94 EXPECT_CALL(*this, signal_data_written());
95 end_write_master_to_slave();
96 begin_write_slave_to_master();
97 EXPECT_CALL(*this, signal_data_written());
98 end_write_slave_to_master();
99 begin_write_master_to_single_slave(1);
100 EXPECT_CALL(*this, signal_data_written());
101 end_write_master_to_single_slave(1);
102}
103
104TEST_F(Transport, writes_from_master_to_all_slaves) {
105 update_transport();
106 test_object1* obj = begin_write_master_to_slave();
107 obj->test = 5;
108 EXPECT_CALL(*this, signal_data_written());
109 end_write_master_to_slave();
110 EXPECT_CALL(*this, router_send_frame(0xFF));
111 update_transport();
112 transport_recv_frame(0, sent_data.data(), sent_data.size());
113 test_object1* obj2 = read_master_to_slave();
114 EXPECT_NE(obj2, nullptr);
115 EXPECT_EQ(obj2->test, 5);
116}
117
118TEST_F(Transport, writes_from_slave_to_master) {
119 update_transport();
120 test_object1* obj = begin_write_slave_to_master();
121 obj->test = 7;
122 EXPECT_CALL(*this, signal_data_written());
123 end_write_slave_to_master();
124 EXPECT_CALL(*this, router_send_frame(0));
125 update_transport();
126 transport_recv_frame(3, sent_data.data(), sent_data.size());
127 test_object1* obj2 = read_slave_to_master(2);
128 EXPECT_EQ(read_slave_to_master(0), nullptr);
129 EXPECT_NE(obj2, nullptr);
130 EXPECT_EQ(obj2->test, 7);
131}
132
133TEST_F(Transport, writes_from_master_to_single_slave) {
134 update_transport();
135 test_object1* obj = begin_write_master_to_single_slave(3);
136 obj->test = 7;
137 EXPECT_CALL(*this, signal_data_written());
138 end_write_master_to_single_slave(3);
139 EXPECT_CALL(*this, router_send_frame(4));
140 update_transport();
141 transport_recv_frame(0, sent_data.data(), sent_data.size());
142 test_object1* obj2 = read_master_to_single_slave();
143 EXPECT_NE(obj2, nullptr);
144 EXPECT_EQ(obj2->test, 7);
145}
146
147TEST_F(Transport, ignores_object_with_invalid_id) {
148 update_transport();
149 test_object1* obj = begin_write_master_to_single_slave(3);
150 obj->test = 7;
151 EXPECT_CALL(*this, signal_data_written());
152 end_write_master_to_single_slave(3);
153 EXPECT_CALL(*this, router_send_frame(4));
154 update_transport();
155 sent_data[sent_data.size() - 1] = 44;
156 transport_recv_frame(0, sent_data.data(), sent_data.size());
157 test_object1* obj2 = read_master_to_single_slave();
158 EXPECT_EQ(obj2, nullptr);
159}
160
161TEST_F(Transport, ignores_object_with_size_too_small) {
162 update_transport();
163 test_object1* obj = begin_write_master_to_slave();
164 obj->test = 7;
165 EXPECT_CALL(*this, signal_data_written());
166 end_write_master_to_slave();
167 EXPECT_CALL(*this, router_send_frame(_));
168 update_transport();
169 sent_data[sent_data.size() - 2] = 0;
170 transport_recv_frame(0, sent_data.data(), sent_data.size() - 1);
171 test_object1* obj2 = read_master_to_slave();
172 EXPECT_EQ(obj2, nullptr);
173}
174
175TEST_F(Transport, ignores_object_with_size_too_big) {
176 update_transport();
177 test_object1* obj = begin_write_master_to_slave();
178 obj->test = 7;
179 EXPECT_CALL(*this, signal_data_written());
180 end_write_master_to_slave();
181 EXPECT_CALL(*this, router_send_frame(_));
182 update_transport();
183 sent_data.resize(sent_data.size() + 22);
184 sent_data[sent_data.size() - 1] = 0;
185 transport_recv_frame(0, sent_data.data(), sent_data.size());
186 test_object1* obj2 = read_master_to_slave();
187 EXPECT_EQ(obj2, nullptr);
188}