• 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 
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