• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <gtest/gtest.h>
7 
8 #include <thread>
9 #include <future>
10 #include <cstring>
11 
12 #include <vsomeip/vsomeip.hpp>
13 #include "../../implementation/utility/include/utility.hpp"
14 #include "../../implementation/configuration/include/configuration.hpp"
15 #include "../../implementation/configuration/include/configuration_plugin.hpp"
16 #include "../../implementation/plugin/include/plugin_manager_impl.hpp"
17 
18 using namespace vsomeip;
19 
20 static const std::string APPLICATION_NAME_ROUTING_MANAGER = "routingmanagerd";
21 
22 static const std::string APPLICATION_NAME_NOT_PREDEFINED = "test-application-name";
23 
24 vsomeip::client_t CLIENT_ID_ROUTING_MANAGER = 0xFFFF;
25 
26 static const std::string APPLICATION_IN_NAME = "client_id_test_utility_service_in";
27 static vsomeip::client_t APPLICATION_IN_CLIENT_ID = 0xFFFF;
28 
29 static const std::string APPLICATION_IN_NAME_TWO = "client_id_test_utility_service_in_two";
30 static vsomeip::client_t APPLICATION_IN_CLIENT_ID_TWO = 0xFFFF;
31 
32 static const std::string APPLICATION_OUT_LOW_NAME = "client_id_test_utility_service_out_low";
33 static const vsomeip::client_t APPLICATION_OUT_LOW_CLIENT_ID = 0x5911;
34 
35 static const std::string APPLICATION_OUT_HIGH_NAME = "client_id_test_utility_service_out_high";
36 static const vsomeip::client_t APPLICATION_OUT_HIGH_CLIENT_ID = 0x7411;
37 
38 class client_id_utility_test: public ::testing::Test {
39 public:
client_id_utility_test()40     client_id_utility_test() :
41             client_id_routing_manager_(0x0),
42             diagnosis_(0x0),
43             diagnosis_mask_(0xFF00),
44             client_id_base_(0x0) {
45 
46         std::shared_ptr<vsomeip::configuration> its_configuration;
47         auto its_plugin = vsomeip::plugin_manager::get()->get_plugin(
48                 vsomeip::plugin_type_e::CONFIGURATION_PLUGIN, VSOMEIP_CFG_LIBRARY);
49         if (its_plugin) {
50             auto its_config_plugin = std::dynamic_pointer_cast<vsomeip::configuration_plugin>(its_plugin);
51             if (its_config_plugin) {
52                 configuration_ = its_config_plugin->get_configuration(APPLICATION_NAME_ROUTING_MANAGER);
53             }
54         }
55     }
56 protected:
SetUp()57     virtual void SetUp() {
58         ASSERT_TRUE(static_cast<bool>(configuration_));
59         configuration_->load(APPLICATION_NAME_ROUTING_MANAGER);
60         diagnosis_mask_ = configuration_->get_diagnosis_mask();
61         diagnosis_ = configuration_->get_diagnosis_address();
62 
63         // calculate all client IDs based on mask
64         client_id_base_ = static_cast<client_t>(diagnosis_ << 8);
65         CLIENT_ID_ROUTING_MANAGER =
66                 static_cast<client_t>((configuration_->get_diagnosis_address()
67                         << 8) & configuration_->get_diagnosis_mask());
68         APPLICATION_IN_CLIENT_ID = static_cast<client_t>(client_id_base_ | 0x11);
69         APPLICATION_IN_CLIENT_ID_TWO = static_cast<client_t>(client_id_base_ | 0x12);
70 
71         app_ = vsomeip::runtime::get()->create_application(APPLICATION_NAME_ROUTING_MANAGER);
72         EXPECT_TRUE(app_->init());
73         EXPECT_EQ(CLIENT_ID_ROUTING_MANAGER, app_->get_client());
74 
75         rm_impl_thread_ = std::thread([&](){
76             app_->start();
77         });
78         // ensure clean preconditions
79         utility::reset_client_ids();
80 
81         // required as there are two static versions of the utility class in this
82         // test, one in the test itself and one in libvsomeip...
83         client_id_routing_manager_ = utility::request_client_id(
84                 configuration_, APPLICATION_NAME_ROUTING_MANAGER, static_cast<client_t>(
85                         (configuration_->get_diagnosis_address() << 8)
86                       & configuration_->get_diagnosis_mask()));
87         EXPECT_EQ(CLIENT_ID_ROUTING_MANAGER, client_id_routing_manager_);
88     }
89 
TearDown()90     virtual void TearDown() {
91         app_->stop();
92         if (rm_impl_thread_.joinable()) {
93             rm_impl_thread_.join();
94         }
95         app_.reset();
96         utility::release_client_id(client_id_routing_manager_);
97     }
98 
99 protected:
100     std::shared_ptr<configuration> configuration_;
101     vsomeip::client_t client_id_routing_manager_;
102     std::uint16_t diagnosis_;
103     std::uint16_t diagnosis_mask_;
104     client_t client_id_base_;
105     std::shared_ptr<vsomeip::application> app_;
106     std::thread rm_impl_thread_;
107 };
108 
109 class app_wrapper {
110 public:
app_wrapper(const std::string & _name)111     app_wrapper(const std::string& _name) :
112         app_(vsomeip::runtime::get()->create_application(_name)),
113         client_(VSOMEIP_CLIENT_UNSET) {
114         EXPECT_TRUE(app_->init());
115         app_->register_state_handler(
116                 std::bind(&app_wrapper::on_state, this, std::placeholders::_1));
117         app_thread_ = std::thread([&](){ app_->start(); });
118     }
119 
~app_wrapper()120     ~app_wrapper() {
121         app_->stop();
122         if (app_thread_.joinable()) {
123             app_thread_.join();
124         }
125         app_.reset();
126     }
127 
on_state(const vsomeip::state_type_e & _state)128     void on_state(const vsomeip::state_type_e& _state) {
129         if (_state == vsomeip::state_type_e::ST_REGISTERED) {
130             client_ = app_->get_client();
131             registered_.set_value();
132         }
133     };
134 
get_client()135     client_t get_client() {
136         if (std::future_status::timeout
137                 == registered_.get_future().wait_for(
138                         std::chrono::seconds(11))) {
139             ADD_FAILURE()<< __LINE__ << " application wasn't registered within time";
140         }
141         return client_;
142     }
143 
get_app()144     std::shared_ptr<vsomeip::application> get_app() {
145         return app_;
146     }
147 
148 private:
149     std::shared_ptr<vsomeip::application> app_;
150     std::promise<void> registered_;
151     std::thread app_thread_;
152     vsomeip::client_t client_;
153 };
154 
TEST_F(client_id_utility_test,request_release_client_id)155 TEST_F(client_id_utility_test, request_release_client_id) {
156     app_wrapper app(APPLICATION_NAME_NOT_PREDEFINED);
157     EXPECT_EQ(client_id_base_ | 0x1, app.get_client());
158 }
159 
TEST_F(client_id_utility_test,request_client_id_twice)160 TEST_F(client_id_utility_test, request_client_id_twice) {
161     app_wrapper app(APPLICATION_NAME_NOT_PREDEFINED);
162     EXPECT_EQ(client_id_base_ | 0x1, app.get_client());
163 
164     app_wrapper app2(APPLICATION_NAME_NOT_PREDEFINED);
165     EXPECT_EQ(client_id_base_ | 0x2, app2.get_client());
166 }
167 
TEST_F(client_id_utility_test,ensure_sequential_ascending_client_id_allocation)168 TEST_F(client_id_utility_test, ensure_sequential_ascending_client_id_allocation) {
169     app_wrapper app(APPLICATION_NAME_NOT_PREDEFINED);
170     EXPECT_EQ(client_id_base_ | 0x1, app.get_client());
171 
172     auto app2 = std::make_shared<app_wrapper>(APPLICATION_NAME_NOT_PREDEFINED);
173     client_t app2_client = app2->get_client();
174     EXPECT_EQ(client_id_base_ | 0x2, app2_client);
175 
176     app2.reset();
177 
178     auto app3 = std::make_shared<app_wrapper>(APPLICATION_NAME_NOT_PREDEFINED);
179     client_t app3_client = app3->get_client();
180     EXPECT_EQ(client_id_base_ | 0x3, app3_client);
181 
182     EXPECT_GT(app3_client, app2_client);
183 
184 }
185 
TEST_F(client_id_utility_test,ensure_preconfigured_client_ids_not_used_for_autoconfig)186 TEST_F(client_id_utility_test, ensure_preconfigured_client_ids_not_used_for_autoconfig)
187 {
188     // request client ids until 10 over the preconfigured one
189     const std::uint16_t limit =
190             static_cast<std::uint16_t>((APPLICATION_IN_CLIENT_ID
191                     & ~diagnosis_mask_) + std::uint16_t(10));
192 
193     std::vector<std::shared_ptr<app_wrapper>> its_apps;
194     its_apps.reserve(limit);
195 
196     for (int i = 0; i < limit; i++ ) {
197         its_apps.emplace_back(
198                 std::make_shared<app_wrapper>(APPLICATION_NAME_NOT_PREDEFINED + std::to_string(i)));
199     }
200     for (const auto& a : its_apps) {
201         EXPECT_NE(APPLICATION_IN_CLIENT_ID, a->get_client());
202     }
203     its_apps.clear();
204 }
205 
TEST_F(client_id_utility_test,request_predefined_client_id_in_diagnosis_range)206 TEST_F(client_id_utility_test,
207         request_predefined_client_id_in_diagnosis_range) {
208     auto app1 = std::make_shared<app_wrapper>(APPLICATION_IN_NAME);
209     EXPECT_EQ(APPLICATION_IN_CLIENT_ID, app1->get_client());
210 }
211 
TEST_F(client_id_utility_test,request_predefined_client_id_in_diagnosis_range_twice)212 TEST_F(client_id_utility_test,
213         request_predefined_client_id_in_diagnosis_range_twice) {
214     auto app1 = std::make_shared<app_wrapper>(APPLICATION_IN_NAME);
215     EXPECT_EQ(APPLICATION_IN_CLIENT_ID, app1->get_client());
216 
217     // preconfigured is already taken -> autogenerated ID should be returned
218     auto app2 = std::make_shared<app_wrapper>(APPLICATION_IN_NAME);
219     EXPECT_EQ(client_id_base_ | 0x1, app2->get_client());
220 }
221 
TEST_F(client_id_utility_test,request_predefined_client_id_outside_diagnosis_range_high)222 TEST_F(client_id_utility_test,
223         request_predefined_client_id_outside_diagnosis_range_high) {
224     auto app1 = std::make_shared<app_wrapper>(APPLICATION_OUT_HIGH_NAME);
225     // we should get the client ID defined in the json file
226     EXPECT_EQ(APPLICATION_OUT_HIGH_CLIENT_ID, app1->get_client());
227 }
228 
TEST_F(client_id_utility_test,request_client_id_with_predefined_app_name_outside_diagnosis_range_high_multiple)229 TEST_F(client_id_utility_test,
230         request_client_id_with_predefined_app_name_outside_diagnosis_range_high_multiple) {
231 
232     auto app1 = std::make_shared<app_wrapper>(APPLICATION_OUT_HIGH_NAME);
233     // we should get the client ID defined in the json file
234     EXPECT_EQ(APPLICATION_OUT_HIGH_CLIENT_ID, app1->get_client());
235 
236     // preconfigured is already taken -> autogenerated ID should be returned
237     auto app2 = std::make_shared<app_wrapper>(APPLICATION_OUT_HIGH_NAME);
238     EXPECT_EQ(client_id_base_ | 0x1, app2->get_client());
239 
240     auto app3 = std::make_shared<app_wrapper>(APPLICATION_OUT_HIGH_NAME);
241     EXPECT_EQ(client_id_base_ | 0x2, app3->get_client());
242 }
243 
TEST_F(client_id_utility_test,request_predefined_client_id_outside_diagnosis_range_low)244 TEST_F(client_id_utility_test,
245         request_predefined_client_id_outside_diagnosis_range_low) {
246     auto app1 = std::make_shared<app_wrapper>(APPLICATION_OUT_LOW_NAME);
247     // we should get the client ID defined in the json file
248     EXPECT_EQ(APPLICATION_OUT_LOW_CLIENT_ID, app1->get_client());
249 }
250 
TEST_F(client_id_utility_test,request_predefined_client_id_outside_diagnosis_range_low_multiple)251 TEST_F(client_id_utility_test,
252         request_predefined_client_id_outside_diagnosis_range_low_multiple) {
253     auto app1 = std::make_shared<app_wrapper>(APPLICATION_OUT_LOW_NAME);
254     // we should get the client ID defined in the json file
255     EXPECT_EQ(APPLICATION_OUT_LOW_CLIENT_ID, app1->get_client());
256 
257     // preconfigured is already taken -> autogenerated ID should be returned
258     auto app2 = std::make_shared<app_wrapper>(APPLICATION_OUT_LOW_NAME);
259     EXPECT_EQ(client_id_base_ | 0x1, app2->get_client());
260 
261     auto app3 = std::make_shared<app_wrapper>(APPLICATION_OUT_LOW_NAME);
262     EXPECT_EQ(client_id_base_ | 0x2, app3->get_client());
263 }
264 
TEST_F(client_id_utility_test,ensure_preconfigured_client_ids_in_diagnosis_range_dont_influence_autoconfig_client_ids)265 TEST_F(client_id_utility_test,
266        ensure_preconfigured_client_ids_in_diagnosis_range_dont_influence_autoconfig_client_ids)
267 {
268     auto app0 = std::make_shared<app_wrapper>(APPLICATION_NAME_NOT_PREDEFINED);
269     EXPECT_EQ(client_id_base_ | 0x1, app0->get_client());
270 
271     auto app1 = std::make_shared<app_wrapper>(APPLICATION_IN_NAME);
272     EXPECT_EQ(APPLICATION_IN_CLIENT_ID, app1->get_client());
273 
274     auto app2 = std::make_shared<app_wrapper>(APPLICATION_IN_NAME_TWO);
275     EXPECT_EQ(APPLICATION_IN_CLIENT_ID_TWO, app2->get_client());
276 
277     auto app3 = std::make_shared<app_wrapper>(APPLICATION_NAME_NOT_PREDEFINED);
278     EXPECT_EQ(client_id_base_ | 0x2, app3->get_client());
279 
280     auto app4 = std::make_shared<app_wrapper>(APPLICATION_NAME_NOT_PREDEFINED);
281     EXPECT_EQ(client_id_base_ | 0x3, app4->get_client());
282 }
283 
TEST_F(client_id_utility_test,exhaust_client_id_range_sequential)284 TEST_F(client_id_utility_test, exhaust_client_id_range_sequential) {
285     std::vector<vsomeip::client_t> its_clients;
286     std::uint16_t its_max_clients(0);
287     for (int var = 0; var < __builtin_popcount(static_cast<std::uint16_t>(~diagnosis_mask_)); ++var) {
288         its_max_clients = static_cast<std::uint16_t>(its_max_clients | (1 << var));
289     }
290     // -2 as two predefined client IDs are present in the json file which
291     // aren't assigned via autoconfiguration
292     const std::uint16_t max_allowed_clients = static_cast<std::uint16_t>(its_max_clients - 2u);
293 
294     // acquire maximum amount of client IDs
295     for (int var = 0; var < 2; ++var) {
296         for (std::uint16_t i = 0; i < max_allowed_clients; i++) {
297             const vsomeip::client_t its_client =
298                     vsomeip::utility::request_client_id(configuration_,
299                             APPLICATION_NAME_NOT_PREDEFINED + std::to_string(i),
300                             VSOMEIP_CLIENT_UNSET);
301             if (its_client != VSOMEIP_CLIENT_UNSET) {
302                 if (i > 0) {
303                     EXPECT_LT(its_clients.back(), its_client);
304                 }
305                 its_clients.push_back(its_client);
306             } else {
307                 ADD_FAILURE() << "Received VSOMEIP_CLIENT_UNSET "
308                         << static_cast<std::uint32_t>(i);
309             }
310         }
311         // check limit is reached
312         EXPECT_EQ(VSOMEIP_CLIENT_UNSET, vsomeip::utility::request_client_id(
313                         configuration_, APPLICATION_NAME_NOT_PREDEFINED + "max",
314                         VSOMEIP_CLIENT_UNSET));
315         for (const auto& c : its_clients) {
316             utility::release_client_id(c);
317         }
318     }
319  }
320 
TEST_F(client_id_utility_test,exhaust_client_id_range_fragmented)321 TEST_F(client_id_utility_test, exhaust_client_id_range_fragmented) {
322     std::vector<client_t> its_clients;
323 
324     // -2 as two predefined client IDs are present in the json file which
325     // aren't assigned via autoconfiguration
326     std::uint16_t its_max_clients(0);
327     for (int var = 0; var < __builtin_popcount(static_cast<std::uint16_t>(~diagnosis_mask_)); ++var) {
328         its_max_clients = static_cast<std::uint16_t>(its_max_clients | (1 << var));
329     }
330     const std::uint16_t max_allowed_clients = static_cast<std::uint16_t>(its_max_clients - 2u);
331 
332     for (int var = 0; var < 2; ++var) {
333         // acquire maximum amount of client IDs
334         for (std::uint16_t i = 0; i < max_allowed_clients; i++) {
335             const vsomeip::client_t its_client =
336                     vsomeip::utility::request_client_id(configuration_,
337                             APPLICATION_NAME_NOT_PREDEFINED + std::to_string(i),
338                             VSOMEIP_CLIENT_UNSET);
339             if (its_client != VSOMEIP_CLIENT_UNSET) {
340                 if ((var == 0 && i > 0) ||
341                     (var == 1 && i > 1) // special case as in the 1st run the last assigned client ID was 63fe
342                                         // due to the releases. In the 2nd run the first client ID therefore will be 63ff
343                     ) {
344                     EXPECT_LT(its_clients.back(), its_client);
345                 }
346                 its_clients.push_back(its_client);
347             } else {
348                 ADD_FAILURE() << "Received VSOMEIP_CLIENT_UNSET "
349                         << static_cast<std::uint32_t>(i);
350             }
351         }
352 
353         // check limit is reached
354         EXPECT_EQ(VSOMEIP_CLIENT_UNSET, vsomeip::utility::request_client_id(
355                         configuration_, APPLICATION_NAME_NOT_PREDEFINED + "max",
356                         VSOMEIP_CLIENT_UNSET));
357 
358         // release every second requested client ID
359         std::vector<client_t> its_released_client_ids;
360         for (size_t i = 0; i < its_clients.size(); i++ ) {
361             if (i % 2) {
362                 its_released_client_ids.push_back(its_clients[i]);
363                 utility::release_client_id(its_clients[i]);
364             }
365         }
366         for (const client_t c : its_released_client_ids) {
367             for (auto it = its_clients.begin(); it != its_clients.end(); ) {
368                 if (*it == c) {
369                     it = its_clients.erase(it);
370                 } else {
371                     ++it;
372                 }
373             }
374         }
375 
376         // acquire client IDs up to the maximum allowed amount again
377         for (std::uint16_t i = 0; i < its_released_client_ids.size(); i++) {
378             const vsomeip::client_t its_client =
379                     vsomeip::utility::request_client_id(configuration_,
380                             APPLICATION_NAME_NOT_PREDEFINED + std::to_string(i),
381                             VSOMEIP_CLIENT_UNSET);
382             if (its_client != VSOMEIP_CLIENT_UNSET) {
383                 if (i > 0) {
384                     EXPECT_LT(its_clients.back(), its_client);
385                 }
386                 its_clients.push_back(its_client);
387             } else {
388                 ADD_FAILURE() << "Received VSOMEIP_CLIENT_UNSET "
389                         << static_cast<std::uint32_t>(i);
390             }
391         }
392 
393         // check limit is reached
394         EXPECT_EQ(VSOMEIP_CLIENT_UNSET, vsomeip::utility::request_client_id(
395                         configuration_, APPLICATION_NAME_NOT_PREDEFINED + "max2",
396                         VSOMEIP_CLIENT_UNSET));
397 
398         // release all
399         for (const auto& c : its_clients) {
400             utility::release_client_id(c);
401         }
402         its_clients.clear();
403     }
404 }
405 
406 /*
407  * @test Check that the autoconfigured client IDs continue to increase even if
408  * some client IDs at the beginning of the range are already released again
409  */
TEST_F(client_id_utility_test,exhaust_client_id_range_fragmented_extended)410 TEST_F(client_id_utility_test, exhaust_client_id_range_fragmented_extended) {
411     std::vector<client_t> its_client_ids;
412 
413     // -1 for the routing manager, -2 as two predefined client IDs are present
414     // in the json file which aren't assigned via autoconfiguration
415     std::uint16_t its_max_clients(0);
416     for (int var = 0; var < __builtin_popcount(static_cast<std::uint16_t>(~diagnosis_mask_)); ++var) {
417         its_max_clients = static_cast<std::uint16_t>(its_max_clients | (1 << var));
418     }
419     const std::uint16_t its_diagnosis_mask = configuration_->get_diagnosis_mask();
420     const std::uint16_t its_client_mask = static_cast<std::uint16_t>(~its_diagnosis_mask);
421     const client_t its_masked_diagnosis_address = static_cast<client_t>(
422             (configuration_->get_diagnosis_address() << 8) & its_diagnosis_mask);
423     const client_t its_biggest_client = its_masked_diagnosis_address | its_client_mask;
424 
425     const std::uint16_t max_possible_clients = its_max_clients;
426     const std::uint16_t intermediate_release = 3;
427     const std::uint16_t max_allowed_clients = static_cast<std::uint16_t>(max_possible_clients - 2u);
428 
429     // acquire (almost) maximum amount of client IDs
430     for (std::uint16_t i = 0; i < max_allowed_clients - intermediate_release; i++) {
431         client_t its_client_id = utility::request_client_id(configuration_,
432                 APPLICATION_NAME_NOT_PREDEFINED + std::to_string(i),
433                 VSOMEIP_CLIENT_UNSET);
434         EXPECT_NE(VSOMEIP_CLIENT_UNSET, its_client_id);
435         if (its_client_id != VSOMEIP_CLIENT_UNSET) {
436             if (i > 0) {
437                 EXPECT_LT(its_client_ids.back(), its_client_id);
438             }
439             its_client_ids.push_back(its_client_id);
440         } else {
441             ADD_FAILURE() << "Received VSOMEIP_CLIENT_UNSET "
442                     << static_cast<std::uint32_t>(i);
443         }
444     }
445 
446     // release the first intermediate_release client IDs again
447     std::vector<client_t> its_intermediate_released_client_ids;
448     for (size_t i = 0; i < intermediate_release; i++ ) {
449         its_intermediate_released_client_ids.push_back(its_client_ids[i]);
450         utility::release_client_id(its_client_ids[i]);
451         its_client_ids.erase(its_client_ids.begin() + i);
452     }
453 
454     // acquire some more client IDs, these should be bigger than the already acquired
455     for (std::uint16_t i = 0; i < intermediate_release; i++) {
456         client_t its_client_id = utility::request_client_id(configuration_,
457                 APPLICATION_NAME_NOT_PREDEFINED + std::to_string(i)
458                         + "intermediate",
459                 VSOMEIP_CLIENT_UNSET);
460         EXPECT_NE(VSOMEIP_CLIENT_UNSET, its_client_id);
461         if (its_client_id != VSOMEIP_CLIENT_UNSET) {
462             EXPECT_LT(its_client_ids.back(), its_client_id);
463             its_client_ids.push_back(its_client_id);
464         } else {
465             ADD_FAILURE() << "Received VSOMEIP_CLIENT_UNSET "
466                     << static_cast<std::uint32_t>(i);
467         }
468     }
469 
470     // check correct wrap around of client IDs
471     for (std::uint16_t i = 0; i < intermediate_release; i++) {
472         client_t its_client_id = utility::request_client_id(configuration_,
473                 APPLICATION_NAME_NOT_PREDEFINED + std::to_string(i),
474                 VSOMEIP_CLIENT_UNSET);
475         EXPECT_NE(VSOMEIP_CLIENT_UNSET, its_client_id);
476         if (its_client_id != VSOMEIP_CLIENT_UNSET) {
477             if (i == 0) {
478                 EXPECT_GT(its_client_ids.back(), its_client_id);
479             } else {
480                 EXPECT_LT(its_client_ids.back(), its_client_id);
481             }
482             its_client_ids.push_back(its_client_id);
483         } else {
484             ADD_FAILURE() << "Received VSOMEIP_CLIENT_UNSET "
485                     << static_cast<std::uint32_t>(i);
486         }
487     }
488 
489     // check limit is reached
490     client_t its_illegal_client_id = utility::request_client_id(configuration_,
491             APPLICATION_NAME_NOT_PREDEFINED, VSOMEIP_CLIENT_UNSET);
492     EXPECT_EQ(VSOMEIP_CLIENT_UNSET, its_illegal_client_id);
493 
494     // release every second requested client ID
495     std::vector<client_t> its_released_client_ids;
496     for (size_t i = 0; i < its_client_ids.size(); i++ ) {
497         if (i % 2) {
498             its_released_client_ids.push_back(its_client_ids[i]);
499             utility::release_client_id(its_client_ids[i]);
500         }
501     }
502     for (const client_t c : its_released_client_ids) {
503         for (auto it = its_client_ids.begin(); it != its_client_ids.end(); ) {
504             if (*it == c) {
505                 it = its_client_ids.erase(it);
506             } else {
507                 ++it;
508             }
509         }
510     }
511 
512     // acquire client IDs up to the maximum allowed amount again
513     for (std::uint16_t i = 0; i < its_released_client_ids.size(); i++) {
514         client_t its_client_id = utility::request_client_id(configuration_,
515                 APPLICATION_NAME_NOT_PREDEFINED + std::to_string(i),
516                 VSOMEIP_CLIENT_UNSET);
517         EXPECT_NE(VSOMEIP_CLIENT_UNSET, its_client_id);
518         if (its_client_id != VSOMEIP_CLIENT_UNSET) {
519             if (i > 0 && its_client_ids.back() != its_biggest_client) {
520                 EXPECT_LT(its_client_ids.back(), its_client_id);
521             }
522             its_client_ids.push_back(its_client_id);
523         } else {
524             ADD_FAILURE() << "Received VSOMEIP_CLIENT_UNSET "
525                     << static_cast<std::uint32_t>(i);
526         }
527     }
528 
529     // check limit is reached
530     its_illegal_client_id = 0xFFFF;
531     its_illegal_client_id = utility::request_client_id(configuration_,
532             APPLICATION_NAME_NOT_PREDEFINED, VSOMEIP_CLIENT_UNSET);
533     EXPECT_EQ(VSOMEIP_CLIENT_UNSET, its_illegal_client_id);
534 
535     // release all
536     for (const client_t c : its_client_ids) {
537         utility::release_client_id(c);
538     }
539 }
540 
TEST_F(client_id_utility_test,request_released_client_id_after_maximum_client_id_is_assigned)541 TEST_F(client_id_utility_test, request_released_client_id_after_maximum_client_id_is_assigned) {
542     std::vector<client_t> its_client_ids;
543     std::uint16_t its_max_clients(0);
544     for (int var = 0; var < __builtin_popcount(static_cast<std::uint16_t>(~diagnosis_mask_)); ++var) {
545         its_max_clients = static_cast<std::uint16_t>(its_max_clients | (1 << var));
546     }
547     const std::uint16_t max_possible_clients = its_max_clients;
548     // -1 for the routing manager, -2 as two predefined client IDs are present
549     // in the json file which aren't assigned via autoconfiguration
550     const std::uint16_t max_allowed_clients = static_cast<std::uint16_t>(max_possible_clients - 2u);
551 
552     // acquire (almost) maximum amount of client IDs
553     for (std::uint16_t i = 0; i < max_allowed_clients - 1; i++) {
554         client_t its_client_id = utility::request_client_id(configuration_,
555                 APPLICATION_NAME_NOT_PREDEFINED, VSOMEIP_CLIENT_UNSET);
556         EXPECT_NE(VSOMEIP_CLIENT_UNSET, its_client_id);
557         if (its_client_id != VSOMEIP_CLIENT_UNSET) {
558             if (i > 0) {
559                 EXPECT_LT(its_client_ids.back(), its_client_id);
560             }
561             its_client_ids.push_back(its_client_id);
562         } else {
563             ADD_FAILURE()<< "Received VSOMEIP_CLIENT_UNSET "
564             << static_cast<std::uint32_t>(i);
565         }
566     }
567 
568     // release a client ID
569     utility::release_client_id(its_client_ids[10]);
570 
571     // requesting an ID should return the maximum possible ID
572     client_t its_max_client_id = utility::request_client_id(configuration_,
573             APPLICATION_NAME_NOT_PREDEFINED, VSOMEIP_CLIENT_UNSET);
574     EXPECT_NE(VSOMEIP_CLIENT_UNSET, its_max_client_id);
575     its_client_ids.push_back(its_max_client_id);
576 
577     // requesting an ID should work as we have released one before
578     client_t its_client_id = utility::request_client_id(configuration_,
579             APPLICATION_NAME_NOT_PREDEFINED, VSOMEIP_CLIENT_UNSET);
580     EXPECT_NE(VSOMEIP_CLIENT_UNSET, its_client_id);
581     its_client_ids.push_back(its_client_id);
582 
583     // requesting an ID should not work as all IDs are in use now
584     client_t its_illegal_client_id = utility::request_client_id(configuration_,
585             APPLICATION_NAME_NOT_PREDEFINED, VSOMEIP_CLIENT_UNSET);
586     EXPECT_EQ(VSOMEIP_CLIENT_UNSET, its_illegal_client_id);
587 
588     // release another ID
589     utility::release_client_id(its_client_ids[5]);
590 
591     its_client_id = utility::request_client_id(configuration_,
592             APPLICATION_NAME_NOT_PREDEFINED, VSOMEIP_CLIENT_UNSET);
593     EXPECT_NE(VSOMEIP_CLIENT_UNSET, its_client_id);
594     its_client_ids.push_back(its_client_id);
595 
596     // release all
597     for (const client_t c : its_client_ids) {
598         utility::release_client_id(c);
599     }
600     its_client_ids.clear();
601 }
602 
603 #ifndef _WIN32
main(int argc,char ** argv)604 int main(int argc, char** argv) {
605     ::testing::InitGoogleTest(&argc, argv);
606     return RUN_ALL_TESTS();
607 }
608 #endif
609