• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2021 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 <condition_variable>
7 #include <mutex>
8 #include <thread>
9 #include <atomic>
10 
11 #include <gtest/gtest.h>
12 
13 #include <vsomeip/vsomeip.hpp>
14 #include <vsomeip/internal/logger.hpp>
15 
16 #include "suspend_resume_test.hpp"
17 
18 pid_t daemon_pid__;
19 
20 class suspend_resume_test_service {
21 public:
suspend_resume_test_service()22     suspend_resume_test_service()
23         : name_("suspend_resume_test_service"),
24           app_(vsomeip::runtime::get()->create_application(name_)),
25           is_running_(true),
26           is_unblocked_(false),
27           runner_(std::bind(&suspend_resume_test_service::run, this)),
28           sr_runner_(std::bind(&suspend_resume_test_service::sr_run, this)) {
29     }
30 
run_test()31     void run_test() {
32 
33         register_state_handler();
34         register_message_handler();
35         register_subscription_handler();
36 
37         start();
38 
39         VSOMEIP_DEBUG << "Using daemon with pid=" << std::dec << daemon_pid__;
40 
41         {
42             std::unique_lock<std::mutex> its_lock(mutex_);
43             auto r = cv_.wait_for(its_lock, std::chrono::seconds(30));
44             EXPECT_EQ(r, std::cv_status::no_timeout);
45         }
46 
47         stop();
48     }
49 
50 private:
start()51     void start() {
52 
53         app_->init();
54         cv_.notify_one();
55     }
56 
stop()57     void stop() {
58 
59         is_running_ = false;
60         sr_cv_.notify_one();
61 
62         app_->stop();
63 
64         runner_.join();
65         sr_runner_.join();
66     }
67 
run()68     void run() {
69 
70         {
71             std::unique_lock<std::mutex> its_lock(mutex_);
72             cv_.wait(its_lock);
73         }
74 
75         app_->start();
76     }
77 
sr_run()78     void sr_run() {
79 
80         while (is_running_) {
81             std::unique_lock<std::mutex> its_lock(sr_mutex_);
82             sr_cv_.wait(its_lock);
83 
84             if (is_running_) {
85                 VSOMEIP_DEBUG << "send kill SIGUSR1 to PID: " << std::dec << daemon_pid__;
86                 kill(daemon_pid__, SIGUSR1);
87                 std::this_thread::sleep_for(std::chrono::seconds(5));
88                 VSOMEIP_DEBUG << "send kill SIGUSR2 to PID: " << std::dec << daemon_pid__;
89                 kill(daemon_pid__, SIGUSR2);
90             }
91         }
92     }
93 
register_state_handler()94     void register_state_handler() {
95 
96         app_->register_state_handler(
97             std::bind(&suspend_resume_test_service::on_state, this, std::placeholders::_1));
98     }
99 
register_message_handler()100     void register_message_handler() {
101 
102         app_->register_message_handler(TEST_SERVICE, TEST_INSTANCE, TEST_METHOD,
103             std::bind(&suspend_resume_test_service::on_message, this,
104                 std::placeholders::_1));
105     }
106 
register_subscription_handler()107     void register_subscription_handler() {
108 
109         app_->register_subscription_handler(TEST_SERVICE, TEST_INSTANCE, TEST_EVENTGROUP,
110             std::bind(&suspend_resume_test_service::on_subscribe, this,
111                     std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
112     }
113 
offer_service()114     void offer_service() {
115         app_->offer_event(TEST_SERVICE, TEST_INSTANCE, TEST_EVENT, { TEST_EVENTGROUP },
116                 vsomeip::event_type_e::ET_FIELD,
117                 std::chrono::milliseconds::zero(), false, true, nullptr,
118                 vsomeip::reliability_type_e::RT_UNRELIABLE);
119 
120         vsomeip::byte_t its_data[] = { 0x1, 0x2, 0x3 };
121         auto its_payload = vsomeip::runtime::get()->create_payload();
122         its_payload->set_data(its_data, sizeof(its_data));
123         app_->notify(TEST_SERVICE, TEST_INSTANCE, TEST_EVENT, its_payload);
124 
125         app_->offer_service(TEST_SERVICE, TEST_INSTANCE, TEST_MAJOR, TEST_MINOR);
126     }
127 
128     // handler
on_state(vsomeip::state_type_e _state)129     void on_state(vsomeip::state_type_e _state) {
130         VSOMEIP_DEBUG << __func__ << ": state="
131             << (_state == vsomeip::state_type_e::ST_REGISTERED ?
132                     "registered." : "NOT registered.");
133 
134         if (_state == vsomeip::state_type_e::ST_REGISTERED) {
135             offer_service();
136         }
137     }
138 
on_message(const std::shared_ptr<vsomeip::message> & _message)139     void on_message(const std::shared_ptr<vsomeip::message> &_message) {
140 
141         VSOMEIP_DEBUG << __func__ << ": Received "
142                 << std::hex << std::setw(4) << std::setfill('0')
143                 << _message->get_service()
144                 << std::hex << std::setw(4) << std::setfill('0')
145                 << _message->get_instance()
146                 << std::hex << std::setw(4) << std::setfill('0')
147                 << _message->get_method();
148 
149         if (_message->get_service() == TEST_SERVICE
150                 && _message->get_instance() == TEST_INSTANCE
151                 && _message->get_method() == TEST_METHOD) {
152 
153             if (_message->get_payload()->get_length() == 1) {
154 
155                 vsomeip::byte_t its_control_byte(*_message->get_payload()->get_data());
156 
157                 switch (its_control_byte) {
158                 case TEST_SUSPEND:
159                     sr_cv_.notify_one();
160                     break;
161                 case TEST_STOP:
162                     cv_.notify_one();
163                     break;
164                 default:
165                     ;
166                 }
167             }
168         }
169     }
170 
on_subscribe(vsomeip::client_t _client,vsomeip::uid_t _uid,vsomeip::gid_t _gid,bool _is_subscribe)171     bool on_subscribe(vsomeip::client_t _client,
172             vsomeip::uid_t _uid, vsomeip::gid_t _gid,
173             bool _is_subscribe) {
174 
175         (void)_client;
176         (void)_uid;
177         (void)_gid;
178 
179         VSOMEIP_DEBUG << __func__ << ": is_subscribe=" << std::boolalpha << _is_subscribe;
180         if (!_is_subscribe)
181             std::this_thread::sleep_for(std::chrono::milliseconds(2000));
182         return (true);
183     }
184 
185 private: // members
186     std::string name_;
187     std::shared_ptr<vsomeip::application> app_;
188     std::atomic<bool> is_running_;
189     bool is_unblocked_;
190     std::mutex mutex_;
191     std::condition_variable cv_;
192     std::mutex sr_mutex_;
193     std::condition_variable sr_cv_;
194     std::thread runner_;
195     std::thread sr_runner_;
196 };
197 
TEST(suspend_resume_test,fast)198 TEST(suspend_resume_test, fast)
199 {
200     suspend_resume_test_service its_service;
201     its_service.run_test();
202 }
203 
204 #ifndef _WIN32
main(int argc,char ** argv)205 int main(int argc, char** argv) {
206 
207     ::testing::InitGoogleTest(&argc, argv);
208 
209     daemon_pid__ = atoi(argv[1]);
210 
211     return RUN_ALL_TESTS();
212 }
213 #endif // _WIN32
214