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