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 <future> 15 #include <atomic> 16 17 #include <gtest/gtest.h> 18 19 #include <vsomeip/vsomeip.hpp> 20 #include <vsomeip/internal/logger.hpp> 21 22 #include "application_test_globals.hpp" 23 24 class application_test_service { 25 public: application_test_service(struct application_test::service_info _service_info)26 application_test_service(struct application_test::service_info _service_info) : 27 service_info_(_service_info), 28 // service with number 1 uses "routingmanagerd" as application name 29 // this way the same json file can be reused for all local tests 30 // including the ones with routingmanagerd 31 app_(vsomeip::runtime::get()->create_application("service")), 32 wait_until_registered_(true), 33 stop_called_(false), 34 offer_thread_(std::bind(&application_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(&application_test_service::on_state, this, 41 std::placeholders::_1)); 42 43 app_->register_message_handler(service_info_.service_id, 44 service_info_.instance_id, service_info_.method_id, 45 std::bind(&application_test_service::on_request, this, 46 std::placeholders::_1)); 47 48 app_->register_message_handler(service_info_.service_id, 49 service_info_.instance_id, service_info_.shutdown_method_id, 50 std::bind(&application_test_service::on_shutdown_method_called, this, 51 std::placeholders::_1)); 52 std::promise<bool> its_promise; 53 application_thread_ = std::thread([&](){ 54 its_promise.set_value(true); 55 app_->start(); 56 }); 57 EXPECT_TRUE(its_promise.get_future().get()); 58 std::this_thread::sleep_for(std::chrono::milliseconds(100)); 59 } 60 ~application_test_service()61 ~application_test_service() { 62 offer_thread_.join(); 63 application_thread_.join(); 64 } 65 66 offer()67 void offer() { 68 app_->offer_service(service_info_.service_id, service_info_.instance_id, 69 service_info_.major_version, service_info_.minor_version); 70 } 71 on_state(vsomeip::state_type_e _state)72 void on_state(vsomeip::state_type_e _state) { 73 VSOMEIP_INFO << "Application " << app_->get_name() << " is " 74 << (_state == vsomeip::state_type_e::ST_REGISTERED ? 75 "registered." : "deregistered."); 76 77 if (_state == vsomeip::state_type_e::ST_REGISTERED) { 78 std::lock_guard<std::mutex> its_lock(mutex_); 79 wait_until_registered_ = false; 80 condition_.notify_one(); 81 } 82 } 83 on_request(const std::shared_ptr<vsomeip::message> & _message)84 void on_request(const std::shared_ptr<vsomeip::message> &_message) { 85 app_->send(vsomeip::runtime::get()->create_response(_message)); 86 VSOMEIP_INFO << "Received a request with Client/Session [" << std::setw(4) 87 << std::setfill('0') << std::hex << _message->get_client() << "/" 88 << std::setw(4) << std::setfill('0') << std::hex 89 << _message->get_session() << "]"; 90 } 91 on_shutdown_method_called(const std::shared_ptr<vsomeip::message> & _message)92 void on_shutdown_method_called(const std::shared_ptr<vsomeip::message> &_message) { 93 (void)_message; 94 stop(); 95 } 96 stop()97 void stop() { 98 stop_called_ = true; 99 app_->stop_offer_service(service_info_.service_id, service_info_.instance_id, 100 service_info_.major_version, service_info_.minor_version); 101 app_->clear_all_handler(); 102 app_->stop(); 103 } 104 run()105 void run() { 106 VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex 107 << service_info_.service_id << "] Running"; 108 std::unique_lock<std::mutex> its_lock(mutex_); 109 while (wait_until_registered_ && !stop_called_) { 110 condition_.wait_for(its_lock, std::chrono::milliseconds(100)); 111 } 112 113 VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex 114 << service_info_.service_id << "] Offering"; 115 offer(); 116 } 117 118 private: 119 struct application_test::service_info service_info_; 120 std::shared_ptr<vsomeip::application> app_; 121 122 bool wait_until_registered_; 123 std::mutex mutex_; 124 std::condition_variable condition_; 125 std::atomic<bool> stop_called_; 126 std::thread offer_thread_; 127 std::thread application_thread_; 128 }; 129