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
10 #include <gtest/gtest.h>
11
12 #include <vsomeip/vsomeip.hpp>
13 #include <vsomeip/internal/logger.hpp>
14
15 #include "suspend_resume_test.hpp"
16
17 class suspend_resume_test_client {
18 public:
suspend_resume_test_client()19 suspend_resume_test_client()
20 : name_("suspend_resume_test_client"),
21 app_(vsomeip::runtime::get()->create_application(name_)),
22 has_received_(false),
23 runner_(std::bind(&suspend_resume_test_client::run, this)) {
24
25 }
26
run_test()27 void run_test() {
28
29 register_state_handler();
30 register_message_handler();
31 register_availability_handler();
32
33 start();
34
35 {
36 VSOMEIP_DEBUG << "Started.";
37 std::unique_lock<std::mutex> its_lock(mutex_);
38 auto r = cv_.wait_for(its_lock, std::chrono::seconds(10));
39 EXPECT_EQ(r, std::cv_status::no_timeout);
40 }
41
42 toggle();
43
44 {
45 VSOMEIP_DEBUG << "Toggled.";
46 std::unique_lock<std::mutex> its_lock(mutex_);
47 if (!has_received_) {
48 auto r = cv_.wait_for(its_lock, std::chrono::seconds(10));
49 EXPECT_EQ(r, std::cv_status::no_timeout);
50 }
51 }
52
53 send_suspend();
54
55 bool was_successful;
56 {
57 VSOMEIP_DEBUG << "Triggered suspend/resume.";
58
59 // Wait for service to become availaber after suspend/resume.
60 std::unique_lock<std::mutex> its_lock(mutex_);
61 auto r = cv_.wait_for(its_lock, std::chrono::seconds(10));
62 EXPECT_EQ(r, std::cv_status::no_timeout);
63
64 // Wait for initial event after suspend/resume.
65 r = cv_.wait_for(its_lock, std::chrono::seconds(10));
66 EXPECT_EQ(r, std::cv_status::no_timeout);
67
68 was_successful = (r == std::cv_status::no_timeout);
69 }
70
71 if (was_successful)
72 send_stop();
73
74 stop();
75 }
76
77 private:
register_state_handler()78 void register_state_handler() {
79
80 app_->register_state_handler(
81 std::bind(&suspend_resume_test_client::on_state, this, std::placeholders::_1));
82 }
83
register_availability_handler()84 void register_availability_handler() {
85
86 app_->register_availability_handler(TEST_SERVICE, TEST_INSTANCE,
87 std::bind(&suspend_resume_test_client::on_availability, this,
88 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
89 }
90
register_message_handler()91 void register_message_handler() {
92
93 app_->register_message_handler(TEST_SERVICE, TEST_INSTANCE, TEST_EVENT,
94 std::bind(&suspend_resume_test_client::on_message, this,
95 std::placeholders::_1));
96 }
97
start()98 void start() {
99
100 app_->init();
101 cv_.notify_one();
102 }
103
run()104 void run() {
105
106 {
107 std::unique_lock<std::mutex> its_lock(mutex_);
108 cv_.wait(its_lock);
109 }
110
111 app_->start();
112 }
113
stop()114 void stop() {
115
116 app_->stop();
117 runner_.join();
118 }
119
on_state(vsomeip::state_type_e _state)120 void on_state(vsomeip::state_type_e _state) {
121
122 VSOMEIP_DEBUG << __func__ << ": state="
123 << (_state == vsomeip::state_type_e::ST_REGISTERED ?
124 "registered." : "NOT registered.");
125
126 if (_state == vsomeip::state_type_e::ST_REGISTERED) {
127 app_->request_event(TEST_SERVICE, TEST_INSTANCE, TEST_EVENT, { TEST_EVENTGROUP });
128 app_->request_service(TEST_SERVICE, TEST_INSTANCE);
129 }
130 }
131
on_availability(vsomeip::service_t _service,vsomeip::instance_t _instance,bool _is_available)132 void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance, bool _is_available) {
133
134 static bool is_available(false);
135
136 if (_service == TEST_SERVICE && _instance == TEST_INSTANCE) {
137
138 VSOMEIP_DEBUG << __func__ << ": Test service is "
139 << (_is_available ? "available." : "NOT available.");
140
141 if (_is_available)
142 cv_.notify_one();
143 else if (is_available)
144 has_received_ = false;
145
146 is_available = _is_available;
147 }
148 }
149
on_message(const std::shared_ptr<vsomeip::message> & _message)150 void on_message(const std::shared_ptr<vsomeip::message> &_message) {
151
152 if (_message->get_service() == TEST_SERVICE
153 && _message->get_instance() == TEST_INSTANCE
154 && _message->get_method() == TEST_EVENT) {
155
156 VSOMEIP_DEBUG << __func__ << ": Received event.";
157 if (!has_received_) {
158 has_received_ = true;
159 cv_.notify_one();
160 }
161 }
162 }
163
toggle()164 void toggle() {
165
166 app_->subscribe(TEST_SERVICE, TEST_INSTANCE, TEST_EVENTGROUP, TEST_MAJOR);
167 std::this_thread::sleep_for(std::chrono::seconds(3));
168 app_->unsubscribe(TEST_SERVICE, TEST_INSTANCE, TEST_EVENTGROUP);
169 app_->subscribe(TEST_SERVICE, TEST_INSTANCE, TEST_EVENTGROUP, TEST_MAJOR);
170 std::this_thread::sleep_for(std::chrono::seconds(2));
171 app_->unsubscribe(TEST_SERVICE, TEST_INSTANCE, TEST_EVENTGROUP);
172 app_->subscribe(TEST_SERVICE, TEST_INSTANCE, TEST_EVENTGROUP, TEST_MAJOR);
173
174 }
175
176
send_suspend()177 void send_suspend() {
178
179 auto its_message = vsomeip::runtime::get()->create_request(false);
180 its_message->set_service(TEST_SERVICE);
181 its_message->set_instance(TEST_INSTANCE);
182 its_message->set_method(TEST_METHOD);
183 its_message->set_interface_version(TEST_MAJOR);
184 its_message->set_message_type(vsomeip::message_type_e::MT_REQUEST_NO_RETURN);
185 its_message->set_return_code(vsomeip::return_code_e::E_OK);
186
187 vsomeip::byte_t its_data[] = { TEST_SUSPEND };
188 auto its_payload = vsomeip::runtime::get()->create_payload();
189 its_payload->set_data(its_data, sizeof(its_data));
190 its_message->set_payload(its_payload);
191
192 app_->send(its_message);
193
194 std::this_thread::sleep_for(std::chrono::milliseconds(50));
195 }
196
send_stop()197 void send_stop() {
198
199 auto its_message = vsomeip::runtime::get()->create_request(false);
200 its_message->set_service(TEST_SERVICE);
201 its_message->set_instance(TEST_INSTANCE);
202 its_message->set_method(TEST_METHOD);
203 its_message->set_interface_version(TEST_MAJOR);
204 its_message->set_message_type(vsomeip::message_type_e::MT_REQUEST_NO_RETURN);
205 its_message->set_return_code(vsomeip::return_code_e::E_OK);
206
207 vsomeip::byte_t its_data[] = { TEST_STOP };
208 auto its_payload = vsomeip::runtime::get()->create_payload();
209 its_payload->set_data(its_data, sizeof(its_data));
210 its_message->set_payload(its_payload);
211
212 app_->send(its_message);
213
214 std::this_thread::sleep_for(std::chrono::milliseconds(50));
215 }
216
217 private: // members
218 std::string name_;
219 std::shared_ptr<vsomeip::application> app_;
220 std::mutex mutex_;
221 std::condition_variable cv_;
222 bool has_received_;
223 std::thread runner_;
224 };
225
TEST(suspend_resume_test,fast)226 TEST(suspend_resume_test, fast)
227 {
228 suspend_resume_test_client its_client;
229 its_client.run_test();
230 }
231
232 #ifndef _WIN32
main(int argc,char ** argv)233 int main(int argc, char** argv) {
234
235 ::testing::InitGoogleTest(&argc, argv);
236
237 return RUN_ALL_TESTS();
238 }
239 #endif // _WIN32
240