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 <atomic>
15 
16 #include <gtest/gtest.h>
17 
18 #include <vsomeip/vsomeip.hpp>
19 #include <vsomeip/internal/logger.hpp>
20 
21 #include "offer_test_globals.hpp"
22 
23 static std::string service_number;
24 
25 class offer_test_service {
26 public:
offer_test_service(struct offer_test::service_info _service_info)27     offer_test_service(struct offer_test::service_info _service_info) :
28             service_info_(_service_info),
29             // service with number 1 uses "routingmanagerd" as application name
30             // this way the same json file can be reused for all local tests
31             // including the ones with routingmanagerd
32             app_(vsomeip::runtime::get()->create_application(
33                         (service_number == "1") ? "routingmanagerd" :
34                                 "offer_test_service" + service_number)),
35             counter_(0),
36             wait_until_registered_(true),
37             shutdown_method_called_(false),
38             offer_thread_(std::bind(&offer_test_service::run, this)) {
39         if (!app_->init()) {
40             ADD_FAILURE() << "Couldn't initialize application";
41             return;
42         }
43         app_->register_state_handler(
44                 std::bind(&offer_test_service::on_state, this,
45                         std::placeholders::_1));
46 
47         // offer field
48         std::set<vsomeip::eventgroup_t> its_eventgroups;
49         its_eventgroups.insert(service_info_.eventgroup_id);
50         app_->offer_event(service_info_.service_id, service_info_.instance_id,
51                 service_info_.event_id, its_eventgroups,
52                 vsomeip::event_type_e::ET_EVENT, std::chrono::milliseconds::zero(),
53                 false, true, nullptr, vsomeip::reliability_type_e::RT_BOTH);
54 
55         inc_counter_and_notify();
56 
57         app_->register_message_handler(service_info_.service_id,
58                 service_info_.instance_id, service_info_.method_id,
59                 std::bind(&offer_test_service::on_request, this,
60                         std::placeholders::_1));
61 
62         app_->register_message_handler(service_info_.service_id,
63                 service_info_.instance_id, service_info_.shutdown_method_id,
64                 std::bind(&offer_test_service::on_shutdown_method_called, this,
65                         std::placeholders::_1));
66         app_->start();
67     }
68 
~offer_test_service()69     ~offer_test_service() {
70         offer_thread_.join();
71     }
72 
offer()73     void offer() {
74         app_->offer_service(service_info_.service_id, service_info_.instance_id);
75         // this is allowed
76         app_->offer_service(service_info_.service_id, service_info_.instance_id);
77         // this is not allowed and will be rejected
78         app_->offer_service(service_info_.service_id, service_info_.instance_id, 33, 4711);
79     }
80 
on_state(vsomeip::state_type_e _state)81     void on_state(vsomeip::state_type_e _state) {
82         VSOMEIP_INFO << "Application " << app_->get_name() << " is "
83         << (_state == vsomeip::state_type_e::ST_REGISTERED ?
84                 "registered." : "deregistered.");
85 
86         if (_state == vsomeip::state_type_e::ST_REGISTERED) {
87             std::lock_guard<std::mutex> its_lock(mutex_);
88             wait_until_registered_ = false;
89             condition_.notify_one();
90         }
91     }
92 
on_request(const std::shared_ptr<vsomeip::message> & _message)93     void on_request(const std::shared_ptr<vsomeip::message> &_message) {
94         app_->send(vsomeip::runtime::get()->create_response(_message));
95     }
96 
on_shutdown_method_called(const std::shared_ptr<vsomeip::message> & _message)97     void on_shutdown_method_called(const std::shared_ptr<vsomeip::message> &_message) {
98         (void)_message;
99         shutdown_method_called_ = true;
100         // this is will trigger a warning
101         app_->stop_offer_service(service_info_.service_id, service_info_.instance_id, 44, 4711);
102         app_->stop_offer_service(service_info_.service_id, service_info_.instance_id);
103         app_->clear_all_handler();
104         app_->stop();
105     }
106 
run()107     void run() {
108         VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
109                 << service_info_.service_id << "] Running";
110         std::unique_lock<std::mutex> its_lock(mutex_);
111         while (wait_until_registered_) {
112             condition_.wait(its_lock);
113         }
114 
115         VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
116                 << service_info_.service_id << "] Offering";
117         offer();
118 
119         VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
120                 << service_info_.service_id << "] Notifying";
121         while(!shutdown_method_called_) {
122             std::this_thread::sleep_for(std::chrono::milliseconds(10));
123             inc_counter_and_notify();
124         }
125     }
126 
inc_counter_and_notify()127     void inc_counter_and_notify() {
128         ++counter_;
129         // set value to field
130         const std::shared_ptr<vsomeip::payload> its_payload(vsomeip::runtime::get()->create_payload());
131         std::vector<vsomeip::byte_t> its_data;
132         its_data.push_back(static_cast<vsomeip::byte_t>((counter_ & 0xFF000000) >> 24));
133         its_data.push_back(static_cast<vsomeip::byte_t>((counter_ & 0xFF0000) >> 16));
134         its_data.push_back(static_cast<vsomeip::byte_t>((counter_ & 0xFF00) >> 8));
135         its_data.push_back(static_cast<vsomeip::byte_t>((counter_ & 0xFF)));
136         its_payload->set_data(its_data);
137         app_->notify(service_info_.service_id, service_info_.instance_id,
138                 service_info_.event_id, its_payload);
139     }
140 
141 private:
142     struct offer_test::service_info service_info_;
143     std::shared_ptr<vsomeip::application> app_;
144     std::uint32_t counter_;
145 
146     bool wait_until_registered_;
147     std::mutex mutex_;
148     std::condition_variable condition_;
149     std::atomic<bool> shutdown_method_called_;
150     std::thread offer_thread_;
151 };
152 
TEST(someip_offer_test,notify_increasing_counter)153 TEST(someip_offer_test, notify_increasing_counter)
154 {
155     offer_test_service its_sample(offer_test::service);
156 }
157 
158 
159 #ifndef _WIN32
main(int argc,char ** argv)160 int main(int argc, char** argv)
161 {
162     ::testing::InitGoogleTest(&argc, argv);
163     if(argc < 2) {
164         std::cerr << "Please specify a service number, like: " << argv[0] << " 2" << std::endl;
165         return 1;
166     }
167 
168     service_number = std::string(argv[1]);
169     return RUN_ALL_TESTS();
170 }
171 #endif
172