4 Copyright (c) 2016 Fred Sundvik
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:
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
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
25 #include "gtest/gtest.h"
26 #include "gmock/gmock.h"
29 using testing::ElementsAreArray;
33 #include "serial_link/protocol/transport.h"
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);
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),
55 class Transport : public testing::Test {
59 add_remote_objects(test_remote_objects, sizeof(test_remote_objects) / sizeof(remote_object_t*));
64 reinitialize_serial_link_transport();
67 MOCK_METHOD0(signal_data_written, void ());
68 MOCK_METHOD1(router_send_frame, void (uint8_t destination));
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));
75 static Transport* Instance;
77 std::vector<uint8_t> sent_data;
80 Transport* Transport::Instance = nullptr;
83 void signal_data_written(void) {
84 Transport::Instance->signal_data_written();
87 void router_send_frame(uint8_t destination, uint8_t* data, uint16_t size) {
88 Transport::Instance->router_send_frame(destination, data, size);
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);
104 TEST_F(Transport, writes_from_master_to_all_slaves) {
106 test_object1* obj = begin_write_master_to_slave();
108 EXPECT_CALL(*this, signal_data_written());
109 end_write_master_to_slave();
110 EXPECT_CALL(*this, router_send_frame(0xFF));
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);
118 TEST_F(Transport, writes_from_slave_to_master) {
120 test_object1* obj = begin_write_slave_to_master();
122 EXPECT_CALL(*this, signal_data_written());
123 end_write_slave_to_master();
124 EXPECT_CALL(*this, router_send_frame(0));
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);
133 TEST_F(Transport, writes_from_master_to_single_slave) {
135 test_object1* obj = begin_write_master_to_single_slave(3);
137 EXPECT_CALL(*this, signal_data_written());
138 end_write_master_to_single_slave(3);
139 EXPECT_CALL(*this, router_send_frame(4));
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);
147 TEST_F(Transport, ignores_object_with_invalid_id) {
149 test_object1* obj = begin_write_master_to_single_slave(3);
151 EXPECT_CALL(*this, signal_data_written());
152 end_write_master_to_single_slave(3);
153 EXPECT_CALL(*this, router_send_frame(4));
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);
161 TEST_F(Transport, ignores_object_with_size_too_small) {
163 test_object1* obj = begin_write_master_to_slave();
165 EXPECT_CALL(*this, signal_data_written());
166 end_write_master_to_slave();
167 EXPECT_CALL(*this, router_send_frame(_));
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);
175 TEST_F(Transport, ignores_object_with_size_too_big) {
177 test_object1* obj = begin_write_master_to_slave();
179 EXPECT_CALL(*this, signal_data_written());
180 end_write_master_to_slave();
181 EXPECT_CALL(*this, router_send_frame(_));
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);