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