1 // Copyright (C) 2014-2019 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 <iostream>
9 #include <sstream>
10 #include <thread>
11 #include <map>
12
13 #include <gtest/gtest.h>
14 #include <vsomeip/vsomeip.hpp>
15 #include <vsomeip/internal/logger.hpp>
16
17 #include "second_address_test_globals.hpp"
18
19 class second_address_test_service {
20 public:
second_address_test_service(struct second_address_test::service_info _service_info)21 second_address_test_service(struct second_address_test::service_info _service_info) :
22 service_info_(_service_info),
23 app_(vsomeip::runtime::get()->create_application("second_address_test_service")),
24 offer_thread_(std::bind(&second_address_test_service::run, this)) {
25
26 if (!app_->init()) {
27 ADD_FAILURE() << "Couldn't initialize application";
28 return;
29 }
30
31 app_->register_state_handler(
32 std::bind(&second_address_test_service::on_state, this,
33 std::placeholders::_1));
34
35 app_->register_message_handler(service_info_.service_id,
36 service_info_.instance_id, service_info_.request_method_id,
37 std::bind(&second_address_test_service::on_message, this,
38 std::placeholders::_1));
39
40 app_->register_message_handler(service_info_.service_id,
41 service_info_.instance_id, service_info_.notify_method_id,
42 std::bind(&second_address_test_service::on_notify, this,
43 std::placeholders::_1));
44
45 app_->register_message_handler(service_info_.service_id,
46 service_info_.instance_id, service_info_.shutdown_method_id,
47 std::bind(&second_address_test_service::on_shutdown_method_called, this,
48 std::placeholders::_1));
49
50 app_->register_subscription_handler(service_info_.service_id,
51 service_info_.instance_id, service_info_.eventgroup_id,
52 std::bind(&second_address_test_service::subscription_handler,
53 this, std::placeholders::_1, std::placeholders::_2,
54 std::placeholders::_3, std::placeholders::_4));
55
56 app_->register_subscription_handler(service_info_.service_id,
57 service_info_.instance_id, service_info_.selective_eventgroup_id,
58 std::bind(&second_address_test_service::selective_subscription_handler,
59 this, std::placeholders::_1, std::placeholders::_2,
60 std::placeholders::_3, std::placeholders::_4));
61
62 app_->start();
63 }
64
~second_address_test_service()65 ~second_address_test_service() {
66 offer_thread_.join();
67 }
68
stop()69 void stop() {
70 app_->stop_offer_service(service_info_.service_id, service_info_.instance_id);
71 app_->clear_all_handler();
72 app_->stop();
73 }
74
75 private:
on_state(vsomeip::state_type_e _state)76 void on_state(vsomeip::state_type_e _state) {
77 VSOMEIP_INFO << "Application " << app_->get_name() << " is "
78 << (_state == vsomeip::state_type_e::ST_REGISTERED ?
79 "registered" : "deregistered") << " on service.";
80
81 if (_state == vsomeip::state_type_e::ST_REGISTERED) {
82 std::lock_guard<std::mutex> its_lock(mutex_);
83 wait_until_registered_ = false;
84 condition_.notify_one();
85 }
86 }
87
on_shutdown_method_called(const std::shared_ptr<vsomeip::message> & _message)88 void on_shutdown_method_called(const std::shared_ptr<vsomeip::message> &_message) {
89 app_->send(vsomeip::runtime::get()->create_response(_message));
90
91 VSOMEIP_WARNING << "************************************************************";
92 VSOMEIP_WARNING << "Shutdown method called on service -> going down!";
93 VSOMEIP_WARNING << "************************************************************";
94
95 std::lock_guard<std::mutex> its_lock(mutex_);
96 wait_until_shutdown_method_called_ = false;
97 condition_.notify_one();
98 }
99
on_message(const std::shared_ptr<vsomeip::message> & _message)100 void on_message(const std::shared_ptr<vsomeip::message> &_message) {
101 EXPECT_EQ(service_info_.service_id, _message->get_service());
102 EXPECT_EQ(service_info_.request_method_id, _message->get_method());
103 EXPECT_EQ(service_info_.instance_id, _message->get_instance());
104
105 std::shared_ptr<vsomeip::message> response = vsomeip::runtime::get()->create_response(_message);
106 response->set_payload(_message->get_payload());
107 app_->send(response);
108
109 std::lock_guard<std::mutex> its_lock(mutex_);
110 messages_received_++;
111
112 if (messages_received_ == second_address_test::number_of_messages_to_send) {
113 wait_until_receive_messages_ = false;
114 condition_.notify_one();
115 }
116 }
117
on_notify(const std::shared_ptr<vsomeip::message> & _message)118 void on_notify(const std::shared_ptr<vsomeip::message> &_message) {
119 EXPECT_EQ(service_info_.service_id, _message->get_service());
120 EXPECT_EQ(service_info_.notify_method_id, _message->get_method());
121 EXPECT_EQ(service_info_.instance_id, _message->get_instance());
122
123 auto its_payload = _message->get_payload();
124 notifications_to_send_ = its_payload->get_data()[0];
125
126 std::lock_guard<std::mutex> its_lock(mutex_);
127 wait_until_notify_method_called_ = false;
128 condition_.notify_one();
129 }
130
offer()131 void offer() {
132 app_->offer_service(service_info_.service_id, service_info_.instance_id);
133
134 std::set<vsomeip::eventgroup_t> its_eventgroups;
135 its_eventgroups.insert(service_info_.eventgroup_id);
136
137 app_->offer_event(service_info_.service_id, service_info_.instance_id,
138 service_info_.event_id, its_eventgroups,
139 vsomeip::event_type_e::ET_EVENT, std::chrono::milliseconds::zero(),
140 false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
141
142 its_eventgroups.clear();
143 its_eventgroups.insert(service_info_.selective_eventgroup_id);
144
145 app_->offer_event(service_info_.service_id, service_info_.instance_id,
146 service_info_.selective_event_id, its_eventgroups,
147 vsomeip::event_type_e::ET_SELECTIVE_EVENT, std::chrono::milliseconds::zero(),
148 false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
149 }
150
notify()151 void notify() {
152 EXPECT_TRUE(client_subscribed_);
153 EXPECT_TRUE(client_subscribed_selective_);
154 auto its_payload = vsomeip::runtime::get()->create_payload();
155
156 std::uint32_t i = 0;
157
158 for (; i < notifications_to_send_; i++) {
159 its_payload->set_data(std::vector<vsomeip::byte_t>(i+1, 0x55));
160 app_->notify(service_info_.service_id, service_info_.instance_id,
161 service_info_.event_id, its_payload);
162 }
163
164 for (; i < 2 * notifications_to_send_; i++) {
165 its_payload->set_data(std::vector<vsomeip::byte_t>(i+1, 0x55));
166 app_->notify_one(service_info_.service_id, service_info_.instance_id,
167 service_info_.selective_event_id, its_payload, client_id_);
168 }
169 }
170
run()171 void run() {
172 VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
173 << service_info_.service_id << "] Running";
174
175 std::unique_lock<std::mutex> its_lock(mutex_);
176 while (wait_until_registered_) {
177 condition_.wait(its_lock);
178 }
179
180 VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
181 << service_info_.service_id << "] Offering";
182 offer();
183
184 while (wait_until_receive_messages_) {
185 condition_.wait(its_lock);
186 }
187
188 VSOMEIP_DEBUG << "Service waiting for notify method has been called";
189 while (wait_until_notify_method_called_) {
190 condition_.wait(its_lock);
191 }
192
193 VSOMEIP_DEBUG << "Service notifying events";
194 notify();
195
196 while (wait_until_shutdown_method_called_) {
197 condition_.wait(its_lock);
198 }
199
200 its_lock.unlock();
201 stop();
202 }
203
subscription_handler(vsomeip::client_t _client,std::uint32_t _uid,std::uint32_t _gid,bool _subscribed)204 bool subscription_handler(vsomeip::client_t _client, std::uint32_t _uid, std::uint32_t _gid, bool _subscribed) {
205 (void)_uid;
206 (void)_gid;
207 VSOMEIP_DEBUG << __func__ << ": client 0x" << std::hex << std::setw(4) << std::setfill('0') << _client
208 << ((_subscribed) ? " subscribed" : "unsubscribed") << " on service.";
209 client_subscribed_ = _subscribed;
210 return true;
211 }
212
selective_subscription_handler(vsomeip::client_t _client,std::uint32_t _uid,std::uint32_t _gid,bool _subscribed)213 bool selective_subscription_handler(vsomeip::client_t _client, std::uint32_t _uid, std::uint32_t _gid, bool _subscribed) {
214 (void)_uid;
215 (void)_gid;
216 VSOMEIP_DEBUG << __func__ << ": client 0x" << std::hex << std::setw(4) << std::setfill('0') << _client
217 << ((_subscribed) ? " subscribed" : "unsubscribed") << " on service.";
218 client_subscribed_selective_ = _subscribed;
219 client_id_ = _client;
220 return true;
221 }
222
223 private:
224 struct second_address_test::service_info service_info_;
225 std::shared_ptr<vsomeip::application> app_;
226
227 bool wait_until_registered_ = true;
228 bool wait_until_receive_messages_ = true;
229 bool wait_until_notify_method_called_ = true;
230 bool wait_until_shutdown_method_called_ = true;
231 bool client_subscribed_ = false;
232 bool client_subscribed_selective_ = false;
233 vsomeip::client_t client_id_ = 0;
234 std::uint32_t messages_received_ = 0;
235 std::uint8_t notifications_to_send_ = 0;
236 std::mutex mutex_;
237 std::condition_variable condition_;
238 std::thread offer_thread_;
239 };
240
TEST(someip_second_address_test,test_communication_with_client)241 TEST(someip_second_address_test, test_communication_with_client)
242 {
243 second_address_test_service its_sample(second_address_test::service);
244 }
245
246 #ifndef _WIN32
main(int argc,char ** argv)247 int main(int argc, char** argv)
248 {
249 ::testing::InitGoogleTest(&argc, argv);
250 return RUN_ALL_TESTS();
251 }
252 #endif
253