• 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 #include <future>
15 #include <atomic>
16 
17 #include <gtest/gtest.h>
18 
19 #include <vsomeip/vsomeip.hpp>
20 #include <vsomeip/internal/logger.hpp>
21 
22 #include "application_test_globals.hpp"
23 
24 class application_test_client {
25 public:
application_test_client(struct application_test::service_info _service_info)26     application_test_client(struct application_test::service_info _service_info) :
27             service_info_(_service_info),
28             app_(vsomeip::runtime::get()->create_application("client")),
29             wait_until_registered_(true),
30             wait_until_service_available_(true),
31             wait_for_stop_(true),
32             received_responses_(0),
33             sent_requests_(0),
34             stop_called_(false),
35             stop_thread_(std::bind(&application_test_client::wait_for_stop, this)),
36             send_thread_(std::bind(&application_test_client::send, this)) {
37         if (!app_->init()) {
38             ADD_FAILURE() << "Couldn't initialize application";
39             return;
40         }
41         app_->register_state_handler(
42                 std::bind(&application_test_client::on_state, this,
43                         std::placeholders::_1));
44 
45         app_->register_message_handler(vsomeip::ANY_SERVICE,
46                 vsomeip::ANY_INSTANCE, vsomeip::ANY_METHOD,
47                 std::bind(&application_test_client::on_message, this,
48                         std::placeholders::_1));
49 
50         // register availability for all other services and request their event.
51         app_->register_availability_handler(service_info_.service_id,
52                 service_info_.instance_id,
53                 std::bind(&application_test_client::on_availability, this,
54                         std::placeholders::_1, std::placeholders::_2,
55                         std::placeholders::_3));
56         app_->request_service(service_info_.service_id,
57                 service_info_.instance_id);
58         std::promise<bool> its_promise;
59         application_thread_ = std::thread([&](){
60             its_promise.set_value(true);
61             app_->start();
62         });
63         EXPECT_TRUE(its_promise.get_future().get());
64         std::this_thread::sleep_for(std::chrono::milliseconds(100));
65     }
66 
~application_test_client()67     ~application_test_client() {
68         send_thread_.join();
69         stop_thread_.join();
70         application_thread_.join();
71     }
72 
on_state(vsomeip::state_type_e _state)73     void on_state(vsomeip::state_type_e _state) {
74         VSOMEIP_INFO << "Application " << app_->get_name() << " is "
75         << (_state == vsomeip::state_type_e::ST_REGISTERED ?
76                 "registered." : "deregistered.");
77 
78         if (_state == vsomeip::state_type_e::ST_REGISTERED) {
79             std::lock_guard<std::mutex> its_lock(mutex_);
80             wait_until_registered_ = false;
81             condition_.notify_one();
82         }
83     }
84 
on_availability(vsomeip::service_t _service,vsomeip::instance_t _instance,bool _is_available)85     void on_availability(vsomeip::service_t _service,
86                          vsomeip::instance_t _instance, bool _is_available) {
87             VSOMEIP_INFO << "Service [" << std::setw(4)
88             << std::setfill('0') << std::hex << _service << "." << _instance
89             << "] is " << (_is_available ? "available":"not available") << ".";
90             std::lock_guard<std::mutex> its_lock(mutex_);
91             if(_is_available) {
92                 wait_until_service_available_ = false;
93                 condition_.notify_one();
94             } else {
95                 wait_until_service_available_ = true;
96                 condition_.notify_one();
97             }
98     }
99 
on_message(const std::shared_ptr<vsomeip::message> & _message)100     void on_message(const std::shared_ptr<vsomeip::message> &_message) {
101         ++received_responses_;
102         EXPECT_EQ(service_info_.service_id, _message->get_service());
103         EXPECT_EQ(service_info_.method_id, _message->get_method());
104         EXPECT_EQ(service_info_.instance_id, _message->get_instance());
105         VSOMEIP_INFO << "Received a response with Client/Session [" << std::setw(4)
106                 << std::setfill('0') << std::hex << _message->get_client() << "/"
107                 << std::setw(4) << std::setfill('0') << std::hex
108                 << _message->get_session() << "]";
109     }
110 
send()111     void send() {
112         std::unique_lock<std::mutex> its_lock(mutex_);
113         while (wait_until_registered_ && !stop_called_) {
114             condition_.wait_for(its_lock, std::chrono::milliseconds(100));
115         }
116 
117         while (wait_until_service_available_  && !stop_called_) {
118             condition_.wait_for(its_lock, std::chrono::milliseconds(100));
119         }
120         its_lock.unlock();
121         its_lock.release();
122 
123         for (;;) {
124             bool send(false);
125             {
126                 std::lock_guard<std::mutex> its_lock(mutex_);
127                 send = !wait_until_service_available_;
128             }
129             if (send && !stop_called_) {
130                 std::shared_ptr<vsomeip::message> its_req = vsomeip::runtime::get()->create_request();
131                 its_req->set_service(service_info_.service_id);
132                 its_req->set_instance(service_info_.instance_id);
133                 its_req->set_method(service_info_.method_id);
134                 app_->send(its_req);
135                 ++sent_requests_;
136                 VSOMEIP_INFO << "Sent a request to the service!";
137                 std::this_thread::sleep_for(std::chrono::milliseconds(100));
138             } else {
139                 std::this_thread::sleep_for(std::chrono::milliseconds(50));
140             }
141             if(stop_called_) {
142                 break;
143             }
144         }
145     }
146 
wait_for_stop()147     void wait_for_stop() {
148         std::unique_lock<std::mutex> its_lock(stop_mutex_);
149         while (wait_for_stop_) {
150             stop_condition_.wait(its_lock);
151         }
152         VSOMEIP_INFO << "going down";
153         app_->clear_all_handler();
154         app_->stop();
155     }
156 
stop(bool check)157     void stop(bool check) {
158         stop_called_ = true;
159         std::lock_guard<std::mutex> its_lock(stop_mutex_);
160         wait_for_stop_ = false;
161         VSOMEIP_INFO << "going down. Sent " << sent_requests_
162                 << " requests and received " << received_responses_
163                 << " responses. Delta: " << sent_requests_ - received_responses_;
164         std::uint32_t counter(0);
165         if (check) {
166             while(sent_requests_ == 0 || sent_requests_ < received_responses_) {
167                 std::this_thread::sleep_for(std::chrono::milliseconds(100));
168                 if(++counter > 50) {
169                     break;
170                 }
171             }
172             EXPECT_GT(sent_requests_, 0u);
173             EXPECT_GT(received_responses_, 0u);
174             EXPECT_EQ(sent_requests_, received_responses_);
175         }
176         stop_condition_.notify_one();
177     }
178 
179 private:
180     struct application_test::service_info service_info_;
181     std::shared_ptr<vsomeip::application> app_;
182 
183     bool wait_until_registered_;
184     bool wait_until_service_available_;
185     std::mutex mutex_;
186     std::condition_variable condition_;
187 
188     bool wait_for_stop_;
189     std::mutex stop_mutex_;
190     std::condition_variable stop_condition_;
191 
192     std::atomic<std::uint32_t> received_responses_;
193     std::atomic<std::uint32_t> sent_requests_;
194     std::atomic<bool> stop_called_;
195 
196     std::thread stop_thread_;
197     std::thread send_thread_;
198     std::thread application_thread_;
199 };
200