]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/serial_link/tests/transport_tests.cpp
Merge branch 'master' of https://github.com/jackhumbert/qmk_firmware
[qmk_firmware.git] / quantum / serial_link / tests / transport_tests.cpp
1 /*
2 The MIT License (MIT)
3
4 Copyright (c) 2016 Fred Sundvik
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23 */
24
25 #include "gtest/gtest.h"
26 #include "gmock/gmock.h"
27
28 using testing::_;
29 using testing::ElementsAreArray;
30 using testing::Args;
31
32 extern "C" {
33 #include "serial_link/protocol/transport.h"
34 }
35
36 struct test_object1 {
37     uint32_t test;
38 };
39
40 struct test_object2 {
41     uint32_t test1;
42     uint32_t test2;
43 };
44
45 MASTER_TO_ALL_SLAVES_OBJECT(master_to_slave, test_object1);
46 MASTER_TO_SINGLE_SLAVE_OBJECT(master_to_single_slave, test_object1);
47 SLAVE_TO_MASTER_OBJECT(slave_to_master, test_object1);
48
49 static 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
55 class Transport : public testing::Test {
56 public:
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
80 Transport* Transport::Instance = nullptr;
81
82 extern "C" {
83 void signal_data_written(void) {
84     Transport::Instance->signal_data_written();
85 }
86
87 void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) {
88     Transport::Instance->router_send_frame(destination, data, size);
89 }
90 }
91
92 TEST_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
104 TEST_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
118 TEST_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
133 TEST_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
147 TEST_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
161 TEST_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
175 TEST_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 }