• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2014-2017 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 
15 #include <gtest/gtest.h>
16 
17 #include <vsomeip/vsomeip.hpp>
18 #include <vsomeip/internal/logger.hpp>
19 
20 #include "client_id_test_globals.hpp"
21 
22 
23 class client_id_test_service {
24 public:
client_id_test_service(struct client_id_test::service_info _service_info)25     client_id_test_service(struct client_id_test::service_info _service_info) :
26             service_info_(_service_info),
27             app_(vsomeip::runtime::get()->create_application()),
28             blocked_(false),
29             offer_thread_(std::bind(&client_id_test_service::run, this)),
30             stopped_(false),
31             stop_thread_(std::bind(&client_id_test_service::wait_for_stop, this)) {
32         if (!app_->init()) {
33             offer_thread_.detach();
34             stop_thread_.detach();
35             ADD_FAILURE() << "Couldn't initialize application";
36             return;
37         }
38         app_->register_state_handler(
39                 std::bind(&client_id_test_service::on_state, this,
40                         std::placeholders::_1));
41         app_->register_message_handler(service_info_.service_id,
42                 service_info_.instance_id, service_info_.method_id,
43                 std::bind(&client_id_test_service::on_request, this,
44                         std::placeholders::_1));
45         app_->register_message_handler(vsomeip::ANY_SERVICE,
46                 service_info_.instance_id, vsomeip::ANY_METHOD,
47                 std::bind(&client_id_test_service::on_response, this,
48                         std::placeholders::_1));
49 
50         for(const auto& i : client_id_test::service_infos) {
51             if ((i.service_id == service_info_.service_id
52                     && i.instance_id == service_info_.instance_id)
53                     || (i.service_id == 0xFFFF && i.instance_id == 0xFFFF)) {
54                 continue;
55             }
56             app_->request_service(i.service_id, i.instance_id);
57             app_->register_availability_handler(i.service_id, i.instance_id,
58                     std::bind(&client_id_test_service::on_availability, this,
59                             std::placeholders::_1, std::placeholders::_2,
60                             std::placeholders::_3));
61 
62             other_services_available_[std::make_pair(i.service_id, i.instance_id)] = false;
63             other_services_received_response_[std::make_pair(i.service_id, i.method_id)] = 0;
64             other_services_received_request_[i.offering_client] = 0;
65         }
66 
67         app_->start();
68     }
69 
~client_id_test_service()70     ~client_id_test_service() {
71         if (offer_thread_.joinable()) {
72             offer_thread_.join();
73         }
74         if (stop_thread_.joinable()) {
75             stop_thread_.join();
76         }
77     }
78 
offer()79     void offer() {
80         app_->offer_service(service_info_.service_id, service_info_.instance_id);
81     }
82 
stop_offer()83     void stop_offer() {
84         app_->stop_offer_service(service_info_.service_id, service_info_.instance_id);
85     }
86 
on_state(vsomeip::state_type_e _state)87     void on_state(vsomeip::state_type_e _state) {
88         VSOMEIP_INFO << "Application " << app_->get_name() << " is "
89         << (_state == vsomeip::state_type_e::ST_REGISTERED ?
90                 "registered." : "deregistered.");
91 
92         if (_state == vsomeip::state_type_e::ST_REGISTERED) {
93             std::lock_guard<std::mutex> its_lock(mutex_);
94             blocked_ = true;
95             condition_.notify_one();
96         }
97     }
98 
on_availability(vsomeip::service_t _service,vsomeip::instance_t _instance,bool _is_available)99     void on_availability(vsomeip::service_t _service,
100                          vsomeip::instance_t _instance, bool _is_available) {
101         if(_is_available) {
102             VSOMEIP_INFO
103             << "[" << std::setw(4) << std::setfill('0') << std::hex
104             << service_info_.service_id << "] Service ["
105             << std::setw(4) << std::setfill('0') << std::hex << _service << "." << _instance
106             << "] is "
107             << (_is_available ? "available." : "NOT available.");
108 
109             auto its_service = other_services_available_.find(std::make_pair(_service, _instance));
110             if(its_service != other_services_available_.end()) {
111                 its_service->second = true;
112             }
113 
114             if(std::all_of(other_services_available_.cbegin(),
115                            other_services_available_.cend(),
116                            [](const std::map<std::pair<vsomeip::service_t,
117                                    vsomeip::instance_t>, bool>::value_type& v) {
118                                 return v.second;})) {
119                 std::lock_guard<std::mutex> its_lock(mutex_);
120                 blocked_ = true;
121                 condition_.notify_one();
122             }
123         }
124     }
125 
on_request(const std::shared_ptr<vsomeip::message> & _message)126     void on_request(const std::shared_ptr<vsomeip::message> &_message) {
127         if(_message->get_message_type() == vsomeip::message_type_e::MT_REQUEST) {
128             VSOMEIP_DEBUG
129             << "[" << std::setw(4) << std::setfill('0') << std::hex
130                         << service_info_.service_id
131             << "] Received a request with Client/Session [" << std::setw(4)
132             << std::setfill('0') << std::hex << _message->get_client() << "/"
133             << std::setw(4) << std::setfill('0') << std::hex
134             << _message->get_session() << "]";
135             std::shared_ptr<vsomeip::message> its_response = vsomeip::runtime::get()
136             ->create_response(_message);
137             app_->send(its_response);
138 
139             other_services_received_request_[_message->get_client()]++;
140             if(all_responses_and_requests_received()) {
141                 std::lock_guard<std::mutex> its_lock(stop_mutex_);
142                 stopped_ = true;
143                 stop_condition_.notify_one();
144             }
145         }
146     }
147 
on_response(const std::shared_ptr<vsomeip::message> & _message)148     void on_response(const std::shared_ptr<vsomeip::message> &_message) {
149         if(_message->get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
150             VSOMEIP_DEBUG
151             << "[" << std::setw(4) << std::setfill('0') << std::hex
152                         << service_info_.service_id
153             << "] Received a response with Client/Session [" << std::setw(4)
154             << std::setfill('0') << std::hex << _message->get_client() << "/"
155             << std::setw(4) << std::setfill('0') << std::hex
156             << _message->get_session() << "] from Service/Method ["
157             << std::setw(4) << std::setfill('0') << std::hex
158             << _message->get_service() << "/" << std::setw(4) << std::setfill('0')
159             << std::hex << _message->get_method() <<"]";
160             other_services_received_response_[std::make_pair(_message->get_service(),
161                                                              _message->get_method())]++;
162 
163             if(all_responses_and_requests_received()) {
164                 std::lock_guard<std::mutex> its_lock(stop_mutex_);
165                 stopped_ = true;
166                 stop_condition_.notify_one();
167             }
168         }
169     }
170 
all_responses_and_requests_received()171     bool all_responses_and_requests_received() {
172         const bool responses = std::all_of(
173                other_services_received_response_.cbegin(),
174                other_services_received_response_.cend(),
175                [](const std::map<std::pair<vsomeip::service_t,
176                        vsomeip::method_t>, std::uint32_t>::value_type& v)
177                { return v.second == client_id_test::messages_to_send;});
178         const bool requests = std::all_of(
179                 other_services_received_request_.cbegin(),
180                 other_services_received_request_.cend(),
181                 [](const std::map<vsomeip::client_t, std::uint32_t>::value_type& v)
182                 { return v.second == client_id_test::messages_to_send;});
183         return (responses && requests);
184     }
185 
run()186     void run() {
187         std::unique_lock<std::mutex> its_lock(mutex_);
188         while (!blocked_) {
189             condition_.wait(its_lock);
190         }
191         blocked_ = false;
192 
193         VSOMEIP_DEBUG  << "[" << std::setw(4) << std::setfill('0') << std::hex
194                     << service_info_.service_id << "] Offering";
195         offer();
196 
197 
198         while (!blocked_) {
199             condition_.wait(its_lock);
200         }
201         blocked_ = false;
202 
203         VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
204                 << service_info_.service_id << "] Sending";
205         // send a message to all other services
206         for (int var = 0; var < client_id_test::messages_to_send; ++var) {
207             for(const client_id_test::service_info& i: client_id_test::service_infos) {
208                 if ((i.service_id == service_info_.service_id
209                                 && i.instance_id == service_info_.instance_id)
210                         || (i.service_id == 0xFFFF && i.instance_id == 0xFFFF)) {
211                     continue;
212                 }
213                 std::shared_ptr<vsomeip::message> msg = vsomeip::runtime::get()->create_request();
214                 msg->set_service(i.service_id);
215                 msg->set_instance(i.instance_id);
216                 msg->set_method(i.method_id);
217                 app_->send(msg);
218                 VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0')
219                         << std::hex << service_info_.service_id
220                         << "] Sending a request to Service/Method ["
221                         << std::setw(4) << std::setfill('0') << std::hex
222                         << i.service_id << "/" << std::setw(4) << std::setfill('0')
223                         << std::hex << i.instance_id <<"]";
224             }
225         }
226 
227         while (!blocked_) {
228             condition_.wait(its_lock);
229         }
230         blocked_ = false;
231     }
232 
wait_for_stop()233     void wait_for_stop() {
234         std::unique_lock<std::mutex> its_lock(stop_mutex_);
235         while (!stopped_) {
236             stop_condition_.wait(its_lock);
237         }
238         VSOMEIP_INFO << "[" << std::setw(4) << std::setfill('0') << std::hex
239                 << service_info_.service_id
240                 << "] Received responses and requests from all other services, going down";
241 
242         // let offer thread exit
243         {
244             std::lock_guard<std::mutex> its_lock(mutex_);
245             blocked_ = true;
246             condition_.notify_one();
247         }
248 
249         std::this_thread::sleep_for(std::chrono::seconds(3));
250         app_->clear_all_handler();
251         app_->stop();
252     }
253 
254 private:
255     client_id_test::service_info service_info_;
256     std::shared_ptr<vsomeip::application> app_;
257     std::map<std::pair<vsomeip::service_t, vsomeip::instance_t>, bool> other_services_available_;
258     std::map<std::pair<vsomeip::service_t, vsomeip::method_t>, std::uint32_t> other_services_received_response_;
259     std::map<vsomeip::client_t, std::uint32_t> other_services_received_request_;
260 
261     bool blocked_;
262     std::mutex mutex_;
263     std::condition_variable condition_;
264     std::thread offer_thread_;
265 
266     bool stopped_;
267     std::mutex stop_mutex_;
268     std::condition_variable stop_condition_;
269     std::thread stop_thread_;
270 };
271 
272 static int service_number;
273 
TEST(someip_client_id_test,send_ten_messages_to_service)274 TEST(someip_client_id_test, send_ten_messages_to_service)
275 {
276     client_id_test_service its_sample(
277             client_id_test::service_infos[static_cast<size_t>(service_number)]);
278 }
279 
280 #ifndef _WIN32
main(int argc,char ** argv)281 int main(int argc, char** argv)
282 {
283     ::testing::InitGoogleTest(&argc, argv);
284     if(argc < 2) {
285         std::cerr << "Please specify a service number, like: " << argv[0] << " 2" << std::endl;
286         std::cerr << "Valid service numbers are in the range of [1,6]" << std::endl;
287         return 1;
288     }
289     service_number = std::stoi(std::string(argv[1]), nullptr);
290     return RUN_ALL_TESTS();
291 }
292 #endif
293