• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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