1 // Copyright (C) 2020 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
2 // This Source Code Form is subject to the terms of the Mozilla Public
3 // License, v. 2.0. If a copy of the MPL was not distributed with this
4 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
6 #include "e2e_profile_04_test_common.hpp"
7 #include "e2e_profile_04_test_client.hpp"
8
9 #include <vsomeip/internal/logger.hpp>
10
11 std::vector<std::vector<vsomeip::byte_t>> responses_;
12 std::vector<std::vector<vsomeip::byte_t>> events_;
13
14 std::map<vsomeip::method_t, uint32_t> counters_;
15
16
e2e_profile_04_test_client()17 e2e_profile_04_test_client::e2e_profile_04_test_client()
18 : app_(vsomeip::runtime::get()->create_application()),
19 is_available_(false),
20 sender_(std::bind(&e2e_profile_04_test_client::run, this)),
21 received_(0) {
22
23 }
24
25 bool
init()26 e2e_profile_04_test_client::init() {
27
28 if (!app_->init()) {
29 ADD_FAILURE() << __func__ << ": Cannot initialize application";
30 return (false);
31 }
32
33 app_->register_state_handler(
34 std::bind(&e2e_profile_04_test_client::on_state, this,
35 std::placeholders::_1));
36
37 app_->register_message_handler(
38 PROFILE_04_SERVICE, PROFILE_04_INSTANCE, vsomeip::ANY_METHOD,
39 std::bind(&e2e_profile_04_test_client::on_message, this,
40 std::placeholders::_1));
41
42 app_->register_availability_handler(
43 PROFILE_04_SERVICE, PROFILE_04_INSTANCE,
44 std::bind(&e2e_profile_04_test_client::on_availability, this,
45 std::placeholders::_1, std::placeholders::_2,
46 std::placeholders::_3));
47
48 return (true);
49 }
50
51 void
start()52 e2e_profile_04_test_client::start() {
53
54 VSOMEIP_INFO << __func__ << ": Starting...";
55 app_->start();
56 }
57
58 void
stop()59 e2e_profile_04_test_client::stop() {
60
61 VSOMEIP_INFO << __func__ << ": Stopping...";
62 shutdown_service();
63 app_->clear_all_handler();
64 app_->stop();
65 }
66
67 void
on_state(vsomeip::state_type_e _state)68 e2e_profile_04_test_client::on_state(vsomeip::state_type_e _state) {
69
70 if (_state == vsomeip::state_type_e::ST_REGISTERED) {
71 app_->request_service(PROFILE_04_SERVICE, PROFILE_04_INSTANCE, false);
72
73 // request event 0x8001, that is protected by E2E Profile 04
74 app_->request_event(PROFILE_04_SERVICE, PROFILE_04_INSTANCE,
75 PROFILE_04_EVENT, { PROFILE_04_EVENTGROUP },
76 vsomeip::event_type_e::ET_FIELD,
77 vsomeip::reliability_type_e::RT_UNRELIABLE);
78 }
79 }
80
81 void
on_availability(vsomeip::service_t _service,vsomeip::instance_t _instance,bool _is_available)82 e2e_profile_04_test_client::on_availability(
83 vsomeip::service_t _service, vsomeip::instance_t _instance,
84 bool _is_available) {
85
86 VSOMEIP_INFO << __func__ << ": Client "
87 << std::hex << std::setw(4) << std::setfill('0')
88 << app_->get_client()
89 << " : Service [" << _service << "." << _instance
90 << "] is " << (_is_available ? "available." : "NOT available.");
91
92 // check that correct service / instance ID gets available
93 if (_is_available) {
94 EXPECT_EQ(PROFILE_04_SERVICE, _service);
95 EXPECT_EQ(PROFILE_04_INSTANCE, _instance);
96 }
97
98 if (PROFILE_04_SERVICE == _service && PROFILE_04_INSTANCE == _instance) {
99 std::unique_lock<std::mutex> its_lock(mutex_);
100 if (is_available_ && !_is_available) {
101 is_available_ = false;
102 } else if(_is_available && !is_available_) {
103 is_available_ = true;
104
105 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
106 app_->subscribe(PROFILE_04_SERVICE, PROFILE_04_INSTANCE,
107 PROFILE_04_EVENTGROUP, PROFILE_04_MAJOR);
108 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
109 condition_.notify_one();
110 }
111 }
112 }
113
114 void
on_message(const std::shared_ptr<vsomeip::message> & _message)115 e2e_profile_04_test_client::on_message(const std::shared_ptr<vsomeip::message> &_message) {
116
117 VSOMEIP_INFO << __func__ << ": Received a message from Service ["
118 << std::setw(4) << std::setfill('0') << std::hex
119 << _message->get_service() << "." << _message->get_instance()
120 << "] to Client/Session ["
121 << _message->get_client() << "/" << _message->get_session()
122 << "]";
123
124 EXPECT_EQ(PROFILE_04_SERVICE, _message->get_service());
125 EXPECT_EQ(PROFILE_04_INSTANCE, _message->get_instance());
126
127 // check fixed payload / CRC in response for service: d025 method: 0001
128 if (vsomeip::message_type_e::MT_RESPONSE == _message->get_message_type()
129 && PROFILE_04_METHOD == _message->get_method()) {
130 // check for calculated CRC status OK for the predefined fixed payload sent by service
131 VSOMEIP_INFO << "Method ID 0x0001 -> IS_VALID_CRC = "
132 << std::boolalpha << _message->is_valid_crc();
133 EXPECT_EQ(true, _message->is_valid_crc());
134
135 // check if payload is as expected as well (including CRC / counter / data ID)
136 std::shared_ptr<vsomeip::payload> its_payload = _message->get_payload();
137 const auto its_data = its_payload->get_data();
138 for (size_t i = 0; i < its_payload->get_length(); i++)
139 EXPECT_EQ(its_data[i], responses_[counters_[PROFILE_04_METHOD]
140 % PROFILE_O4_NUM_MESSAGES][i]);
141
142 counters_[PROFILE_04_METHOD]++;
143
144 } else if (vsomeip::message_type_e::MT_NOTIFICATION == _message->get_message_type()
145 && PROFILE_04_EVENT == _message->get_method()) {
146
147 // check CRC / payload calculated by sender for event 0x8001 against expected payload
148 // check for calculated CRC status OK for the calculated CRC / payload sent by service
149 VSOMEIP_INFO << __func__ << ": Event 0x8001 -> IS_VALID_CRC = "
150 << std::boolalpha << _message->is_valid_crc();
151 EXPECT_EQ(true, _message->is_valid_crc());
152
153 // check if payload is as expected as well (including CRC / counter / data ID nibble)
154 std::shared_ptr<vsomeip::payload> its_payload = _message->get_payload();
155 const auto its_data = its_payload->get_data();
156 for (size_t i = 0; i< its_payload->get_length(); i++)
157 EXPECT_EQ(its_data[i], events_[counters_[PROFILE_04_EVENT]
158 % PROFILE_O4_NUM_MESSAGES][i]);
159
160 counters_[PROFILE_04_EVENT]++;
161 }
162
163 received_++;
164 if (received_ == PROFILE_O4_NUM_MESSAGES * 2) {
165 VSOMEIP_WARNING << __func__ << ": Client"
166 << std::setw(4) << std::setfill('0') << std::hex
167 << app_->get_client()
168 << " received all messages ~> going down!";
169 }
170 }
171
172 void
run()173 e2e_profile_04_test_client::run() {
174
175 for (int i = 0; i < PROFILE_O4_NUM_MESSAGES; ++i) {
176 {
177 std::unique_lock<std::mutex> its_lock(mutex_);
178 while (!is_available_) {
179 condition_.wait(its_lock);
180 }
181 }
182
183 auto request = vsomeip::runtime::get()->create_request(false);
184 request->set_service(PROFILE_04_SERVICE);
185 request->set_instance(PROFILE_04_INSTANCE);
186 request->set_interface_version(PROFILE_04_MAJOR);
187
188 // send a request which is not e2e protected and expect an
189 // protected answer holding a fixed payload (E2E Profile 04)
190 // this call triggers also an event 0x8001 which holds a
191 // calculated payload
192 request->set_method(PROFILE_04_METHOD);
193
194 app_->send(request);
195
196 std::this_thread::sleep_for(std::chrono::milliseconds(250));
197 }
198
199 stop();
200 }
201
202 void
join_sender_thread()203 e2e_profile_04_test_client::join_sender_thread() {
204
205 if (sender_.joinable()) {
206 sender_.join();
207 }
208 }
209
210 void
shutdown_service()211 e2e_profile_04_test_client::shutdown_service() {
212
213 auto request = vsomeip::runtime::get()->create_request(false);
214 request->set_service(PROFILE_04_SERVICE);
215 request->set_instance(PROFILE_04_INSTANCE);
216 request->set_method(PROFILE_04_SHUTDOWN);
217 request->set_interface_version(PROFILE_04_MAJOR);
218
219 app_->send(request);
220
221 std::this_thread::sleep_for(std::chrono::milliseconds(250));
222
223 // expect 10 responses + 10 events
224 EXPECT_EQ(received_, PROFILE_O4_NUM_MESSAGES * 2);
225 }
226
TEST(someip_e2e_profile_04_test,test_crc_calculation)227 TEST(someip_e2e_profile_04_test, test_crc_calculation) {
228
229 e2e_profile_04_test_client test_client;
230
231 if (test_client.init()) {
232 test_client.start();
233 test_client.join_sender_thread();
234 }
235 }
236
main(int argc,char ** argv)237 int main(int argc, char** argv) {
238
239 responses_ = {
240 {
241 0x00, 0x50, 0x00, 0x00, 0x01, 0x00, 0x00, 0x2d,
242 0xaa, 0x1d, 0x3f, 0xdf, 0x08, 0xb7, 0xf4, 0x4c,
243 0x00, 0x00, 0x09, 0x3d, 0x00, 0x01, 0x06, 0xfe,
244 0x01, 0x3e, 0x4c, 0xcc, 0xcd, 0x80, 0x3f, 0xb2,
245 0x3d, 0x83, 0x3e, 0xba, 0x68, 0xed, 0x3f, 0xb3,
246 0x7a, 0xf2, 0xbd, 0x96, 0xc1, 0x42, 0x3d, 0x25,
247 0x1a, 0x62, 0xbd, 0xae, 0x77, 0xf3, 0x3f, 0x80,
248 0x00, 0x00, 0xfc, 0x01, 0x01, 0x3c, 0x1d, 0xbd,
249 0x4e, 0x01, 0x01, 0x3c, 0x2b, 0x87, 0xed, 0x00
250 },
251 {
252 0x00, 0x50, 0x00, 0x01, 0x01, 0x00, 0x00, 0x2d,
253 0xe7, 0xb7, 0x13, 0x87, 0x0c, 0x69, 0x02, 0x1c,
254 0x00, 0x00, 0x09, 0x3d, 0x00, 0x01, 0x06, 0xfe,
255 0x01, 0x3e, 0x4c, 0xcc, 0xcd, 0x80, 0x3f, 0xb2,
256 0x3c, 0x2f, 0x3e, 0xba, 0x46, 0x81, 0x3f, 0xb3,
257 0x73, 0x8d, 0xbd, 0x93, 0xcb, 0xae, 0x3c, 0xf7,
258 0xd2, 0x58, 0xbd, 0xa2, 0x6e, 0xcd, 0x3f, 0x80,
259 0x00, 0x00, 0xfc, 0x01, 0x01, 0x3c, 0x1c, 0x89,
260 0x24, 0x01, 0x01, 0x3c, 0x2b, 0x24, 0x45, 0x00
261 },
262 {
263 0x00, 0x50, 0x00, 0x02, 0x01, 0x00, 0x00, 0x2d,
264 0xb6, 0x19, 0x94, 0x2c, 0x10, 0x1b, 0x28, 0xae,
265 0x00, 0x00, 0x09, 0x3d, 0x00, 0x01, 0x06, 0xfe,
266 0x01, 0x3e, 0x4c, 0xcc, 0xcd, 0x80, 0x3f, 0xb2,
267 0x3e, 0xf3, 0x3e, 0xba, 0x97, 0x45, 0x3f, 0xb3,
268 0x86, 0x81, 0xbd, 0x8a, 0xda, 0xc2, 0x3c, 0xf6,
269 0x00, 0x7a, 0xbd, 0xb4, 0xf9, 0xb9, 0x3f, 0x80,
270 0x00, 0x00, 0xfc, 0x01, 0x01, 0x3c, 0x1c, 0x1b,
271 0x72, 0x01, 0x01, 0x3c, 0x2a, 0x9e, 0x1f, 0x00
272 }
273 };
274
275 events_ = {
276 {
277 0x00, 0x50, 0x8f, 0x81, 0x01, 0x00, 0x00, 0x2d,
278 0xed, 0x6e, 0x78, 0x8d, 0x08, 0xb7, 0xf4, 0x4c,
279 0x00, 0x00, 0x09, 0x3d, 0x00, 0x01, 0x06, 0xfe,
280 0x01, 0x3e, 0x4c, 0xcc, 0xcd, 0x80, 0x3f, 0xb2,
281 0x3d, 0x83, 0x3e, 0xba, 0x68, 0xed, 0x3f, 0xb3,
282 0x7a, 0xf2, 0xbd, 0x96, 0xc1, 0x42, 0x3d, 0x25,
283 0x1a, 0x62, 0xbd, 0xae, 0x77, 0xf3, 0x3f, 0x80,
284 0x00, 0x00, 0xfc, 0x01, 0x01, 0x3c, 0x1d, 0xbd,
285 0x4e, 0x01, 0x01, 0x3c, 0x2b, 0x87, 0xed, 0x00
286 },
287 {
288 0x00, 0x50, 0x8f, 0x82, 0x01, 0x00, 0x00, 0x2d,
289 0x9d, 0xbb, 0x49, 0x3f, 0x0c, 0x69, 0x02, 0x1c,
290 0x00, 0x00, 0x09, 0x3d, 0x00, 0x01, 0x06, 0xfe,
291 0x01, 0x3e, 0x4c, 0xcc, 0xcd, 0x80, 0x3f, 0xb2,
292 0x3c, 0x2f, 0x3e, 0xba, 0x46, 0x81, 0x3f, 0xb3,
293 0x73, 0x8d, 0xbd, 0x93, 0xcb, 0xae, 0x3c, 0xf7,
294 0xd2, 0x58, 0xbd, 0xa2, 0x6e, 0xcd, 0x3f, 0x80,
295 0x00, 0x00, 0xfc, 0x01, 0x01, 0x3c, 0x1c, 0x89,
296 0x24, 0x01, 0x01, 0x3c, 0x2b, 0x24, 0x45, 0x00
297 },
298 {
299 0x00, 0x50, 0x8f, 0x83, 0x01, 0x00, 0x00, 0x2d,
300 0x13, 0x04, 0xf8, 0x81, 0x10, 0x1b, 0x28, 0xae,
301 0x00, 0x00, 0x09, 0x3d, 0x00, 0x01, 0x06, 0xfe,
302 0x01, 0x3e, 0x4c, 0xcc, 0xcd, 0x80, 0x3f, 0xb2,
303 0x3e, 0xf3, 0x3e, 0xba, 0x97, 0x45, 0x3f, 0xb3,
304 0x86, 0x81, 0xbd, 0x8a, 0xda, 0xc2, 0x3c, 0xf6,
305 0x00, 0x7a, 0xbd, 0xb4, 0xf9, 0xb9, 0x3f, 0x80,
306 0x00, 0x00, 0xfc, 0x01, 0x01, 0x3c, 0x1c, 0x1b,
307 0x72, 0x01, 0x01, 0x3c, 0x2a, 0x9e, 0x1f, 0x00
308 }
309 };
310
311 ::testing::InitGoogleTest(&argc, argv);
312 return RUN_ALL_TESTS();
313 }
314