• 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 <atomic>
15 #include <future>
16 
17 #include <gtest/gtest.h>
18 
19 #include <vsomeip/vsomeip.hpp>
20 #include <vsomeip/internal/logger.hpp>
21 
22 #include "pending_subscription_test_globals.hpp"
23 
24 class pending_subscription_test_service {
25 public:
pending_subscription_test_service(struct pending_subscription_test::service_info _service_info,pending_subscription_test::test_mode_e _testmode)26     pending_subscription_test_service(struct pending_subscription_test::service_info _service_info, pending_subscription_test::test_mode_e _testmode) :
27             service_info_(_service_info),
28             testmode_(_testmode),
29             app_(vsomeip::runtime::get()->create_application("pending_subscription_test_service")),
30             wait_until_registered_(true),
31             wait_until_shutdown_method_called_(true),
32             subscription_accepted_asynchronous_(false),
33             subscription_accepted_synchronous_(false),
34             offer_thread_(std::bind(&pending_subscription_test_service::run, this)) {
35         if (!app_->init()) {
36             ADD_FAILURE() << "Couldn't initialize application";
37             return;
38         }
39         app_->register_state_handler(
40                 std::bind(&pending_subscription_test_service::on_state, this,
41                         std::placeholders::_1));
42 
43         // offer field
44         std::set<vsomeip::eventgroup_t> its_eventgroups;
45         its_eventgroups.insert(_service_info.eventgroup_id);
46         app_->offer_event(service_info_.service_id, 0x1,
47                     service_info_.event_id,
48                     its_eventgroups, vsomeip::event_type_e::ET_FIELD,
49                     std::chrono::milliseconds::zero(),
50                     false, true, nullptr, vsomeip::reliability_type_e::RT_UNRELIABLE);
51 
52         its_eventgroups.clear();
53         its_eventgroups.insert(static_cast<vsomeip::eventgroup_t>(_service_info.eventgroup_id+1u));
54 
55         app_->offer_event(service_info_.service_id, 0x1,
56                 static_cast<vsomeip::event_t>(service_info_.event_id+1u),
57                 its_eventgroups, vsomeip::event_type_e::ET_FIELD,
58                 std::chrono::milliseconds::zero(),
59                 false, true, nullptr, vsomeip::reliability_type_e::RT_UNRELIABLE);
60 
61         app_->register_message_handler(vsomeip::ANY_SERVICE,
62                 vsomeip::ANY_INSTANCE, service_info_.shutdown_method_id,
63                 std::bind(&pending_subscription_test_service::on_shutdown_method_called, this,
64                         std::placeholders::_1));
65 
66         app_->register_message_handler(vsomeip::ANY_SERVICE,
67                 vsomeip::ANY_INSTANCE, service_info_.notify_method_id,
68                 std::bind(&pending_subscription_test_service::on_notify_method_called, this,
69                         std::placeholders::_1));
70 
71         app_->register_async_subscription_handler(service_info_.service_id,
72                 0x1, service_info_.eventgroup_id,
73                 std::bind(&pending_subscription_test_service::subscription_handler_async,
74                           this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
75                           std::placeholders::_4, std::placeholders::_5));
76         app_->register_subscription_handler(service_info_.service_id,
77                 0x1, static_cast<vsomeip::eventgroup_t>(service_info_.eventgroup_id+1u),
78                 std::bind(&pending_subscription_test_service::subscription_handler,
79                           this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
80                           std::placeholders::_4));
81         app_->start();
82     }
83 
~pending_subscription_test_service()84     ~pending_subscription_test_service() {
85         offer_thread_.join();
86     }
87 
offer()88     void offer() {
89         app_->offer_service(service_info_.service_id, 0x1);
90     }
91 
stop()92     void stop() {
93         app_->stop_offer_service(service_info_.service_id, 0x1);
94         app_->clear_all_handler();
95         app_->stop();
96     }
97 
on_state(vsomeip::state_type_e _state)98     void on_state(vsomeip::state_type_e _state) {
99         VSOMEIP_INFO << "Application " << app_->get_name() << " is "
100         << (_state == vsomeip::state_type_e::ST_REGISTERED ?
101                 "registered." : "deregistered.");
102 
103         if (_state == vsomeip::state_type_e::ST_REGISTERED) {
104             std::lock_guard<std::mutex> its_lock(mutex_);
105             wait_until_registered_ = false;
106             condition_.notify_one();
107         }
108     }
109 
on_shutdown_method_called(const std::shared_ptr<vsomeip::message> & _message)110     void on_shutdown_method_called(const std::shared_ptr<vsomeip::message> &_message) {
111         app_->send(vsomeip::runtime::get()->create_response(_message));
112         VSOMEIP_WARNING << "************************************************************";
113         VSOMEIP_WARNING << "Shutdown method called -> going down!";
114         VSOMEIP_WARNING << "************************************************************";
115         std::lock_guard<std::mutex> its_lock(mutex_);
116         wait_until_shutdown_method_called_ = false;
117         condition_.notify_one();
118     }
119 
on_notify_method_called(const std::shared_ptr<vsomeip::message> & _message)120     void on_notify_method_called(const std::shared_ptr<vsomeip::message> &_message) {
121         (void)_message;
122         std::shared_ptr<vsomeip::payload> its_payload = vsomeip::runtime::get()->create_payload();
123         its_payload->set_data( {0xDD});
124         app_->notify(service_info_.service_id, service_info_.instance_id,
125                 service_info_.event_id, its_payload);
126         app_->notify(service_info_.service_id, service_info_.instance_id,
127                 static_cast<vsomeip::event_t>(service_info_.event_id + 1u) , its_payload);
128         notify_method_called_.set_value(true);
129     }
130 
run()131     void run() {
132         VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
133                 << service_info_.service_id << "] Running";
134         std::unique_lock<std::mutex> its_lock(mutex_);
135         while (wait_until_registered_) {
136             condition_.wait(its_lock);
137         }
138 
139         VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
140                 << service_info_.service_id << "] Offering";
141         offer();
142 
143         if (testmode_ == pending_subscription_test::test_mode_e::REQUEST_TO_SD) {
144             // this testcase won't send valid subscriptions -> ensure to exit
145             subscription_accepted_asynchronous_ = true;
146             subscription_accepted_synchronous_ = true;
147         }
148 
149         while (!subscription_accepted_asynchronous_ || !subscription_accepted_synchronous_) {
150             std::this_thread::sleep_for(std::chrono::milliseconds(100));
151         }
152         switch (testmode_) {
153             case pending_subscription_test::test_mode_e::SUBSCRIBE:
154                 async_subscription_handler_(true);
155                 break;
156             case pending_subscription_test::test_mode_e::SUBSCRIBE_UNSUBSCRIBE:
157             case pending_subscription_test::test_mode_e::UNSUBSCRIBE:
158             case pending_subscription_test::test_mode_e::SUBSCRIBE_UNSUBSCRIBE_NACK:
159             case pending_subscription_test::test_mode_e::SUBSCRIBE_UNSUBSCRIBE_SAME_PORT:
160             case pending_subscription_test::test_mode_e::SUBSCRIBE_RESUBSCRIBE_MIXED:
161             case pending_subscription_test::test_mode_e::SUBSCRIBE_STOPSUBSCRIBE_SUBSCRIBE:
162             case pending_subscription_test::test_mode_e::REQUEST_TO_SD:
163             default:
164                 break;
165         }
166 
167         std::future<bool> itsFuture = notify_method_called_.get_future();
168         if (std::future_status::timeout == itsFuture.wait_for(std::chrono::seconds(30))) {
169             ADD_FAILURE() << "notify method wasn't called within time!";
170         } else {
171             EXPECT_TRUE(itsFuture.get());
172         }
173         while (wait_until_shutdown_method_called_) {
174             condition_.wait(its_lock);
175         }
176         std::this_thread::sleep_for(std::chrono::milliseconds(2000));
177         stop();
178     }
179 
subscription_handler_async(vsomeip::client_t _client,std::uint32_t _uid,std::uint32_t _gid,bool _subscribed,const std::function<void (const bool)> & _cbk)180     void subscription_handler_async(vsomeip::client_t _client, std::uint32_t _uid, std::uint32_t _gid,
181                                     bool _subscribed, const std::function<void(const bool)>& _cbk) {
182         (void)_uid;
183         (void)_gid;
184         VSOMEIP_WARNING << __func__ << " " << std::hex << _client << " subscribed." << _subscribed;
185         if (testmode_ == pending_subscription_test::test_mode_e::SUBSCRIBE) {
186             async_subscription_handler_ = _cbk;
187             static int was_called = 0;
188             was_called++;
189             EXPECT_EQ(1, was_called);
190             EXPECT_TRUE(_subscribed);
191             subscription_accepted_asynchronous_ = true;
192         } else if (testmode_ == pending_subscription_test::test_mode_e::SUBSCRIBE_UNSUBSCRIBE) {
193             static int count_subscribe = 0;
194             static int count_unsubscribe = 0;
195             _subscribed ? count_subscribe++ : count_unsubscribe++;
196             if (count_subscribe == 1) {
197                 std::this_thread::sleep_for(std::chrono::milliseconds(500));
198             }
199             _cbk(true);
200             if (count_subscribe == 8 || count_unsubscribe == 7) {
201                 subscription_accepted_asynchronous_ = true;
202             }
203         } else if (testmode_ == pending_subscription_test::test_mode_e::UNSUBSCRIBE) {
204             static int count_subscribe = 0;
205             static int count_unsubscribe = 0;
206             _subscribed ? count_subscribe++ : count_unsubscribe++;
207             if (count_subscribe == 1) {
208                 std::this_thread::sleep_for(std::chrono::milliseconds(500));
209             }
210             _cbk(true);
211             if (count_subscribe == 2 || count_unsubscribe == 1) {
212                 subscription_accepted_asynchronous_ = true;
213             }
214         } else if (testmode_ == pending_subscription_test::test_mode_e::SUBSCRIBE_UNSUBSCRIBE_NACK) {
215             static int count_subscribe = 0;
216             static int count_unsubscribe = 0;
217             _subscribed ? count_subscribe++ : count_unsubscribe++;
218             if (count_subscribe == 1) {
219                 std::this_thread::sleep_for(std::chrono::milliseconds(500));
220             }
221             if (_subscribed) {
222                 _cbk(((count_subscribe + 1) % 2)); // nack every second subscription
223             } else {
224                 _cbk(true);
225             }
226             if (count_subscribe == 8 || count_unsubscribe == 7) {
227                 subscription_accepted_asynchronous_ = true;
228             }
229         } else if (testmode_ == pending_subscription_test::test_mode_e::SUBSCRIBE_UNSUBSCRIBE_SAME_PORT) {
230             static int count_subscribe = 0;
231             static int count_unsubscribe = 0;
232             _subscribed ? count_subscribe++ : count_unsubscribe++;
233             if (count_subscribe == 1) {
234                 std::this_thread::sleep_for(std::chrono::milliseconds(500));
235             }
236             _cbk(true);
237             if (count_subscribe == 8 || count_unsubscribe == 7) {
238                 subscription_accepted_asynchronous_ = true;
239             }
240         } else if (testmode_ == pending_subscription_test::test_mode_e::SUBSCRIBE_RESUBSCRIBE_MIXED) {
241             static int was_called = 0;
242             was_called++;
243             EXPECT_EQ(1, was_called);
244             EXPECT_TRUE(_subscribed);
245             _cbk(true);
246             subscription_accepted_asynchronous_ = true;
247         }  else if (testmode_ == pending_subscription_test::test_mode_e::SUBSCRIBE_STOPSUBSCRIBE_SUBSCRIBE) {
248             static int was_called = 0;
249             was_called++;
250             EXPECT_EQ(1, was_called);
251             EXPECT_TRUE(_subscribed);
252             subscription_accepted_asynchronous_ = true;
253             // this test doesn't subscribe to the second eventgroup which is handled by the asynchronous
254             // subscription handler, set it to true here:
255             subscription_accepted_synchronous_ = true;
256             _cbk(true);
257         }
258     }
259 
subscription_handler(vsomeip::client_t _client,std::uint32_t _uid,std::uint32_t _gid,bool _subscribed)260     bool subscription_handler(vsomeip::client_t _client, std::uint32_t _uid, std::uint32_t _gid, bool _subscribed) {
261         (void)_subscribed;
262         (void)_uid;
263         (void)_gid;
264         bool ret(false);
265         VSOMEIP_WARNING << __func__ << " " << std::hex << _client << " subscribed. " << _subscribed;
266         if (testmode_ == pending_subscription_test::test_mode_e::SUBSCRIBE) {
267             static int was_called = 0;
268             was_called++;
269             EXPECT_EQ(1, was_called);
270             EXPECT_TRUE(_subscribed);
271             subscription_accepted_synchronous_ = true;
272             ret = true;
273         } else if (testmode_ == pending_subscription_test::test_mode_e::SUBSCRIBE_UNSUBSCRIBE) {
274             static int count_subscribed = 0;
275             static int count_unsubscribe = 0;
276             _subscribed ? count_subscribed++ : count_unsubscribe++;
277             if (count_subscribed == 1) {
278                 std::this_thread::sleep_for(std::chrono::milliseconds(500));
279             }
280             if (count_subscribed == 8 && count_unsubscribe == 7) {
281                 subscription_accepted_synchronous_ = true;
282             }
283             ret = true;
284         } else if (testmode_ == pending_subscription_test::test_mode_e::UNSUBSCRIBE) {
285             static int count_subscribed = 0;
286             static int count_unsubscribe = 0;
287             _subscribed ? count_subscribed++ : count_unsubscribe++;
288             if (count_subscribed == 1) {
289                 std::this_thread::sleep_for(std::chrono::milliseconds(500));
290             }
291             if (count_subscribed == 2 && count_unsubscribe == 1) {
292                 subscription_accepted_synchronous_ = true;
293             }
294             ret = true;
295         } else if (testmode_ == pending_subscription_test::test_mode_e::SUBSCRIBE_UNSUBSCRIBE_NACK) {
296             static int count_subscribed = 0;
297             static int count_unsubscribe = 0;
298             _subscribed ? count_subscribed++ : count_unsubscribe++;
299             if (count_subscribed == 1) {
300                 std::this_thread::sleep_for(std::chrono::milliseconds(500));
301             }
302             if (count_subscribed == 8 && count_unsubscribe == 7) {
303                 subscription_accepted_synchronous_ = true;
304             }
305             if (_subscribed) {
306                 ret = ((count_subscribed + 1) % 2); // nack every second subscription
307             } else {
308                 ret = true;
309             }
310         } else if (testmode_ == pending_subscription_test::test_mode_e::SUBSCRIBE_UNSUBSCRIBE_SAME_PORT) {
311             static int count_subscribed = 0;
312             static int count_unsubscribe = 0;
313             _subscribed ? count_subscribed++ : count_unsubscribe++;
314 
315             if (count_subscribed == 1) {
316                 std::this_thread::sleep_for(std::chrono::milliseconds(500));
317             }
318             if (count_subscribed == 8 && count_unsubscribe == 7) {
319                 subscription_accepted_synchronous_ = true;
320             }
321             ret = true;
322         } else if (testmode_ == pending_subscription_test::test_mode_e::SUBSCRIBE_RESUBSCRIBE_MIXED) {
323             static int was_called = 0;
324             was_called++;
325             EXPECT_EQ(1, was_called);
326             EXPECT_TRUE(_subscribed);
327             subscription_accepted_synchronous_ = true;
328             ret = true;
329         }
330         return ret;
331     }
332 
333 private:
334     struct pending_subscription_test::service_info service_info_;
335     pending_subscription_test::test_mode_e testmode_;
336     std::shared_ptr<vsomeip::application> app_;
337 
338     bool wait_until_registered_;
339     bool wait_until_shutdown_method_called_;
340     std::mutex mutex_;
341     std::condition_variable condition_;
342     std::atomic<bool> subscription_accepted_asynchronous_;
343     std::atomic<bool> subscription_accepted_synchronous_;
344     std::thread offer_thread_;
345     std::function<void(const bool)> async_subscription_handler_;
346     std::promise<bool> notify_method_called_;
347 };
348 
349 pending_subscription_test::test_mode_e its_testmode(pending_subscription_test::test_mode_e::SUBSCRIBE);
350 
TEST(someip_pending_subscription_test,block_subscription_handler)351 TEST(someip_pending_subscription_test, block_subscription_handler)
352 {
353     pending_subscription_test_service its_sample(pending_subscription_test::service, its_testmode);
354 }
355 
356 
357 #ifndef _WIN32
main(int argc,char ** argv)358 int main(int argc, char** argv)
359 {
360     ::testing::InitGoogleTest(&argc, argv);
361     if (argc < 2) {
362         std::cerr << "Please pass a test mode to this binary like: "
363                 << argv[0] << " SUBSCRIBE" << std::endl;
364         std::cerr << "Testmodes are [SUBSCRIBE, SUBSCRIBE_UNSUBSCRIBE, UNSUBSCRIBE, SUBSCRIBE_UNSUBSCRIBE_NACK, SUBSCRIBE_UNSUBSCRIBE_SAME_PORT]" << std::endl;
365         exit(1);
366     }
367 
368     std::string its_pased_testmode = argv[1];
369     if (its_pased_testmode == std::string("SUBSCRIBE")) {
370         its_testmode = pending_subscription_test::test_mode_e::SUBSCRIBE;
371     } else if (its_pased_testmode == std::string("SUBSCRIBE_UNSUBSCRIBE")) {
372         its_testmode = pending_subscription_test::test_mode_e::SUBSCRIBE_UNSUBSCRIBE;
373     } else if (its_pased_testmode == std::string("UNSUBSCRIBE")) {
374         its_testmode = pending_subscription_test::test_mode_e::UNSUBSCRIBE;
375     } else if (its_pased_testmode == std::string("SUBSCRIBE_UNSUBSCRIBE_NACK")) {
376         its_testmode = pending_subscription_test::test_mode_e::SUBSCRIBE_UNSUBSCRIBE_NACK;
377     } else if (its_pased_testmode == std::string("SUBSCRIBE_UNSUBSCRIBE_SAME_PORT")) {
378         its_testmode = pending_subscription_test::test_mode_e::SUBSCRIBE_UNSUBSCRIBE_SAME_PORT;
379     } else if (its_pased_testmode == std::string("SUBSCRIBE_RESUBSCRIBE_MIXED")) {
380         its_testmode = pending_subscription_test::test_mode_e::SUBSCRIBE_RESUBSCRIBE_MIXED;
381     } else if (its_pased_testmode == std::string("SUBSCRIBE_STOPSUBSCRIBE_SUBSCRIBE")) {
382         its_testmode = pending_subscription_test::test_mode_e::SUBSCRIBE_STOPSUBSCRIBE_SUBSCRIBE;
383     } else if (its_pased_testmode == std::string("REQUEST_TO_SD")) {
384         its_testmode = pending_subscription_test::test_mode_e::REQUEST_TO_SD;
385     }
386 
387     return RUN_ALL_TESTS();
388 }
389 #endif
390