1 // Copyright (C) 2014-2018 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 <chrono>
7 #include <condition_variable>
8 #include <iomanip>
9 #include <iostream>
10 #include <sstream>
11 #include <thread>
12 #include <map>
13 #include <algorithm>
14 #include <atomic>
15
16 #include <gtest/gtest.h>
17
18 #include <vsomeip/vsomeip.hpp>
19 #include <vsomeip/internal/logger.hpp>
20
21 #include "second_address_test_globals.hpp"
22
23 class second_address_test_client {
24 public:
second_address_test_client(struct second_address_test::service_info _service_info,bool _use_tcp)25 second_address_test_client(struct second_address_test::service_info _service_info, bool _use_tcp) :
26 service_info_(_service_info),
27 use_tcp_(_use_tcp),
28 app_(vsomeip::runtime::get()->create_application("second_address_test_client")),
29 send_thread_(std::bind(&second_address_test_client::send, this)) {
30
31 if (!app_->init()) {
32 ADD_FAILURE() << "Couldn't initialize application";
33 return;
34 }
35
36 app_->register_state_handler(
37 std::bind(&second_address_test_client::on_state, this,
38 std::placeholders::_1));
39
40 app_->register_message_handler(service_info_.service_id,
41 service_info_.instance_id, service_info_.request_method_id,
42 std::bind(&second_address_test_client::on_message, this,
43 std::placeholders::_1));
44
45 app_->register_message_handler(service_info_.service_id,
46 service_info_.instance_id, service_info_.event_id,
47 std::bind(&second_address_test_client::on_notification, this,
48 std::placeholders::_1, false));
49
50 app_->register_message_handler(service_info_.service_id,
51 service_info_.instance_id, service_info_.selective_event_id,
52 std::bind(&second_address_test_client::on_notification, this,
53 std::placeholders::_1, true));
54
55 app_->register_message_handler(service_info_.service_id,
56 service_info_.instance_id, service_info_.shutdown_method_id,
57 std::bind(&second_address_test_client::on_shutdown_method_called, this,
58 std::placeholders::_1));
59
60 // register availability for all other services and request their event.
61 app_->register_availability_handler(service_info_.service_id,
62 service_info_.instance_id,
63 std::bind(&second_address_test_client::on_availability, this,
64 std::placeholders::_1, std::placeholders::_2,
65 std::placeholders::_3));
66
67 app_->request_service(service_info_.service_id,
68 service_info_.instance_id);
69
70 app_->register_subscription_status_handler(service_info_.service_id,
71 service_info_.instance_id, service_info_.eventgroup_id,
72 service_info_.event_id,
73 std::bind(&second_address_test_client::on_subscription_status_changed, this,
74 std::placeholders::_1, std::placeholders::_2,
75 std::placeholders::_3, std::placeholders::_4,
76 std::placeholders::_5, false));
77
78 app_->register_subscription_status_handler(service_info_.service_id,
79 service_info_.instance_id, service_info_.selective_eventgroup_id,
80 service_info_.selective_event_id,
81 std::bind(&second_address_test_client::on_subscription_status_changed, this,
82 std::placeholders::_1, std::placeholders::_2,
83 std::placeholders::_3, std::placeholders::_4,
84 std::placeholders::_5, true));
85
86 app_->start();
87 }
88
~second_address_test_client()89 ~second_address_test_client() {
90 send_thread_.join();
91 }
92
subscribe()93 void subscribe() {
94 std::set<vsomeip::eventgroup_t> its_eventgroups;
95 its_eventgroups.insert(service_info_.eventgroup_id);
96
97 app_->request_event(service_info_.service_id,
98 service_info_.instance_id, service_info_.event_id,
99 its_eventgroups, vsomeip::event_type_e::ET_EVENT);
100
101 its_eventgroups.clear();
102 its_eventgroups.insert(service_info_.selective_eventgroup_id);
103
104 app_->request_event(service_info_.service_id,
105 service_info_.instance_id, service_info_.selective_event_id,
106 its_eventgroups, vsomeip::event_type_e::ET_SELECTIVE_EVENT);
107
108 app_->subscribe(service_info_.service_id, service_info_.instance_id,
109 service_info_.eventgroup_id);
110
111 app_->subscribe(service_info_.service_id, service_info_.instance_id,
112 service_info_.selective_eventgroup_id);
113 }
114
on_state(vsomeip::state_type_e _state)115 void on_state(vsomeip::state_type_e _state) {
116 VSOMEIP_DEBUG << "Application " << app_->get_name() << " is "
117 << (_state == vsomeip::state_type_e::ST_REGISTERED ?
118 "registered" : "deregistered") << " on client.";
119
120 if (_state == vsomeip::state_type_e::ST_REGISTERED) {
121 std::lock_guard<std::mutex> its_lock(mutex_);
122 wait_until_registered_ = false;
123 condition_.notify_one();
124 }
125 }
126
on_availability(vsomeip::service_t _service,vsomeip::instance_t _instance,bool _is_available)127 void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance,
128 bool _is_available) {
129
130 VSOMEIP_DEBUG << "Service [" << std::setw(4)
131 << std::setfill('0') << std::hex << _service << "." << _instance
132 << "] is " << (_is_available ? "available":"not available") << " on client.";
133
134 if (_is_available) {
135 std::lock_guard<std::mutex> its_lock(mutex_);
136 wait_until_service_available_ = false;
137 condition_.notify_one();
138 }
139 }
140
on_message(const std::shared_ptr<vsomeip::message> & _message)141 void on_message(const std::shared_ptr<vsomeip::message> &_message) {
142 EXPECT_EQ(service_info_.service_id, _message->get_service());
143 EXPECT_EQ(service_info_.instance_id, _message->get_instance());
144 EXPECT_EQ(service_info_.request_method_id, _message->get_method());
145
146 std::lock_guard<std::mutex> its_lock(mutex_);
147 auto its_payload = _message->get_payload();
148 std::uint32_t data = static_cast<std::uint32_t>(its_payload->get_data()[0]);
149
150 EXPECT_EQ(reply_received_, data);
151
152 wait_until_reply_received_ = false;
153 reply_received_++;
154 condition_.notify_one();
155 }
156
on_notification(const std::shared_ptr<vsomeip::message> & _message,bool _selective)157 void on_notification(const std::shared_ptr<vsomeip::message> &_message,
158 bool _selective) {
159 EXPECT_EQ(service_info_.service_id, _message->get_service());
160 EXPECT_EQ(service_info_.instance_id, _message->get_instance());
161
162 static vsomeip::length_t length_last_received_msg(0);
163 EXPECT_GT(_message->get_payload()->get_length(), length_last_received_msg);
164 length_last_received_msg = _message->get_payload()->get_length();
165
166 if (_selective) {
167 EXPECT_EQ(service_info_.selective_event_id, _message->get_method());
168
169 if (++number_selective_events_received_ == second_address_test::number_of_events_to_send) {
170 std::lock_guard<std::mutex> its_lock(mutex_);
171 wait_until_selective_events_received_ = false;
172 condition_.notify_one();
173 }
174 } else {
175 EXPECT_EQ(service_info_.event_id, _message->get_method());
176
177 if (++number_events_received_ == second_address_test::number_of_events_to_send) {
178 std::lock_guard<std::mutex> its_lock(mutex_);
179 wait_until_events_received_ = false;
180 condition_.notify_one();
181 }
182 }
183 }
184
on_subscription_status_changed(const vsomeip::service_t _service,const vsomeip::instance_t _instance,const vsomeip::eventgroup_t _eventgroup,const vsomeip::event_t _event,const uint16_t error_code,bool _selective)185 void on_subscription_status_changed(const vsomeip::service_t _service,
186 const vsomeip::instance_t _instance,
187 const vsomeip::eventgroup_t _eventgroup,
188 const vsomeip::event_t _event,
189 const uint16_t error_code,
190 bool _selective) {
191
192 VSOMEIP_DEBUG << "Subscription status changed on client";
193
194 EXPECT_EQ(service_info_.service_id, _service);
195 EXPECT_EQ(service_info_.instance_id, _instance);
196 EXPECT_TRUE((error_code == 0x0u || error_code == 0x7u));
197
198 if (_selective) {
199 EXPECT_EQ(service_info_.selective_eventgroup_id, _eventgroup);
200 EXPECT_EQ(service_info_.selective_event_id, _event);
201
202 if (error_code == 0x0u) { // accepted
203 std::lock_guard<std::mutex> its_lock(mutex_);
204 wait_until_selective_subscription_accepted_ = false;
205 condition_.notify_one();
206 }
207
208 } else {
209 EXPECT_EQ(service_info_.eventgroup_id, _eventgroup);
210 EXPECT_EQ(service_info_.event_id, _event);
211
212 if (error_code == 0x0u) { // accepted
213 std::lock_guard<std::mutex> its_lock(mutex_);
214 wait_until_subscription_accepted_ = false;
215 condition_.notify_one();
216 }
217 }
218 }
219
on_shutdown_method_called(const std::shared_ptr<vsomeip::message> & _message)220 void on_shutdown_method_called(const std::shared_ptr<vsomeip::message> &_message) {
221 EXPECT_EQ(service_info_.service_id, _message->get_service());
222 EXPECT_EQ(service_info_.instance_id, _message->get_instance());
223 EXPECT_EQ(service_info_.shutdown_method_id, _message->get_method());
224
225 std::lock_guard<std::mutex> its_lock(mutex_);
226 wait_until_shutdown_reply_received_ = false;
227 condition_.notify_one();
228 }
229
send()230 void send() {
231 std::unique_lock<std::mutex> its_lock(mutex_);
232 while (wait_until_registered_) {
233 condition_.wait(its_lock);
234 }
235
236 while (wait_until_service_available_) {
237 condition_.wait(its_lock);
238 }
239
240 auto its_message = vsomeip::runtime::get()->create_request(use_tcp_);
241 its_message->set_service(service_info_.service_id);
242 its_message->set_instance(service_info_.instance_id);
243 its_message->set_method(service_info_.request_method_id);
244 its_message->set_message_type(vsomeip::message_type_e::MT_REQUEST);
245
246 auto its_payload = vsomeip::runtime::get()->create_payload();
247
248 VSOMEIP_DEBUG << "Client sending request messages";
249
250 for (std::uint32_t index = 0; index < second_address_test::number_of_messages_to_send; index++) {
251 vsomeip::byte_t *msg_payload = reinterpret_cast<vsomeip::byte_t *>(&index);
252 its_payload->set_data(msg_payload, sizeof(index));
253 its_message->set_payload(its_payload);
254 app_->send(its_message);
255
256 wait_until_reply_received_ = true;
257 message_sent_++;
258
259 while (wait_until_reply_received_) {
260 condition_.wait(its_lock);
261 }
262 }
263
264 VSOMEIP_DEBUG << "Client subscribing events";
265
266 subscribe();
267 while (wait_until_subscription_accepted_ || wait_until_selective_subscription_accepted_) {
268 condition_.wait(its_lock);
269 }
270
271 VSOMEIP_DEBUG << "Client requesting event notification";
272
273 its_message->set_method(service_info_.notify_method_id);
274 its_message->set_message_type(vsomeip::message_type_e::MT_REQUEST_NO_RETURN);
275 its_payload->set_data(&second_address_test::number_of_events_to_send, 1);
276 its_message->set_payload(its_payload);
277 app_->send(its_message);
278
279 VSOMEIP_DEBUG << "Client waiting event notification";
280
281 while (wait_until_events_received_ || wait_until_selective_events_received_) {
282 condition_.wait(its_lock);
283 }
284
285 VSOMEIP_DEBUG << "Client shutting down the service";
286
287 // shutdown service
288 its_message->set_method(service_info_.shutdown_method_id);
289 its_message->set_message_type(vsomeip::message_type_e::MT_REQUEST);
290 app_->send(its_message);
291
292 while (wait_until_shutdown_reply_received_) {
293 if (std::cv_status::timeout == condition_.wait_for(its_lock, std::chrono::seconds(30))) {
294 VSOMEIP_ERROR << "Shutdown request wasn't answered in time!";
295 break;
296 }
297 }
298
299 VSOMEIP_INFO << "Client going down";
300 app_->clear_all_handler();
301 app_->stop();
302 }
303
304
305 private:
306 struct second_address_test::service_info service_info_;
307 bool use_tcp_;
308 std::shared_ptr<vsomeip::application> app_;
309
310 bool wait_until_registered_ = true;
311 bool wait_until_service_available_ = true;
312 bool wait_until_subscription_accepted_ = true;
313 bool wait_until_selective_subscription_accepted_ = true;
314 bool wait_until_shutdown_reply_received_ = true;
315 bool wait_until_reply_received_ = true;
316 bool wait_until_events_received_ = true;
317 bool wait_until_selective_events_received_ = true;
318 std::mutex mutex_;
319 std::condition_variable condition_;
320
321 std::thread send_thread_;
322 std::uint32_t message_sent_ = 0;
323 std::uint32_t reply_received_ = 0;
324 std::uint32_t number_events_received_ = 0;
325 std::uint32_t number_selective_events_received_ = 0;
326 };
327
328 static bool use_tcp = false;
329
TEST(someip_event_test,communicate_using_second_address)330 TEST(someip_event_test, communicate_using_second_address)
331 {
332 second_address_test_client its_sample(second_address_test::service, use_tcp);
333 }
334
335 #ifndef _WIN32
main(int argc,char ** argv)336 int main(int argc, char** argv)
337 {
338 ::testing::InitGoogleTest(&argc, argv);
339 if (argc < 2) {
340 std::cerr << "Please specify a communication mode, like: " << argv[0] << " TCP" << std::endl;
341 std::cerr << "Valid communication modes are UDP or TCP" << std::endl;
342 return 1;
343 }
344
345 if (std::string("TCP")== std::string(argv[1])) {
346 use_tcp = true;
347 } else if (std::string("UDP")== std::string(argv[1])) {
348 use_tcp = false;
349 }
350
351 return RUN_ALL_TESTS();
352 }
353 #endif
354