|
20 | 20 | #include <gtest/gtest.h> |
21 | 21 |
|
22 | 22 | #include <fastcdr/Cdr.h> |
| 23 | +#include <fastcdr/CdrSizeCalculator.hpp> |
23 | 24 | #include "utility.hpp" |
24 | 25 |
|
25 | 26 | using namespace eprosima::fastcdr; |
@@ -276,6 +277,131 @@ void deserialize( |
276 | 277 | } // namespace fastcdr |
277 | 278 | } // namespace eprosima |
278 | 279 |
|
| 280 | +struct SizeThreeStruct |
| 281 | +{ |
| 282 | +public: |
| 283 | + |
| 284 | + SizeThreeStruct() = default; |
| 285 | + |
| 286 | + SizeThreeStruct( |
| 287 | + eprosima::fastcdr::EncodingAlgorithmFlag e1, |
| 288 | + eprosima::fastcdr::EncodingAlgorithmFlag e2 |
| 289 | + ) |
| 290 | + : enc_xcdrv1(e1) |
| 291 | + , enc_xcdrv2(e2) |
| 292 | + { |
| 293 | + } |
| 294 | + |
| 295 | + SizeThreeStruct( |
| 296 | + eprosima::fastcdr::EncodingAlgorithmFlag e1, |
| 297 | + eprosima::fastcdr::EncodingAlgorithmFlag e2, |
| 298 | + uint8_t value1, |
| 299 | + uint8_t value2, |
| 300 | + uint8_t value3 |
| 301 | + ) |
| 302 | + : aval(value1) |
| 303 | + , bval(value2) |
| 304 | + , cval(value3) |
| 305 | + , enc_xcdrv1(e1) |
| 306 | + , enc_xcdrv2(e2) |
| 307 | + { |
| 308 | + } |
| 309 | + |
| 310 | + bool operator ==( |
| 311 | + const SizeThreeStruct& other) const |
| 312 | + { |
| 313 | + return aval == other.aval && |
| 314 | + bval == other.bval && |
| 315 | + cval == other.cval; |
| 316 | + } |
| 317 | + |
| 318 | + uint8_t aval; |
| 319 | + uint8_t bval; |
| 320 | + uint8_t cval; |
| 321 | + |
| 322 | + eprosima::fastcdr::EncodingAlgorithmFlag enc_xcdrv1 {eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR}; |
| 323 | + |
| 324 | + eprosima::fastcdr::EncodingAlgorithmFlag enc_xcdrv2 {eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR2}; |
| 325 | +}; |
| 326 | + |
| 327 | +namespace eprosima { |
| 328 | +namespace fastcdr { |
| 329 | + |
| 330 | +template<> |
| 331 | +size_t calculate_serialized_size( |
| 332 | + eprosima::fastcdr::CdrSizeCalculator& calculator, |
| 333 | + const SizeThreeStruct& data, |
| 334 | + size_t& current_alignment) |
| 335 | +{ |
| 336 | + eprosima::fastcdr::EncodingAlgorithmFlag previous_encoding = calculator.get_encoding(); |
| 337 | + eprosima::fastcdr::EncodingAlgorithmFlag new_encoding = calculator.get_cdr_version() == |
| 338 | + eprosima::fastcdr::CdrVersion::XCDRv1 |
| 339 | + ? data.enc_xcdrv1 |
| 340 | + : data.enc_xcdrv2; |
| 341 | + size_t calculated_size {calculator.begin_calculate_type_serialized_size(new_encoding, current_alignment)}; |
| 342 | + |
| 343 | + |
| 344 | + calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId( |
| 345 | + 0), data.aval, current_alignment); |
| 346 | + calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId( |
| 347 | + 1), data.bval, current_alignment); |
| 348 | + calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId( |
| 349 | + 2), data.cval, current_alignment); |
| 350 | + |
| 351 | + calculated_size += calculator.end_calculate_type_serialized_size(previous_encoding, current_alignment); |
| 352 | + |
| 353 | + return calculated_size; |
| 354 | +} |
| 355 | + |
| 356 | +template<> |
| 357 | +void serialize( |
| 358 | + Cdr& cdr, |
| 359 | + const SizeThreeStruct& data) |
| 360 | +{ |
| 361 | + Cdr::state current_status(cdr); |
| 362 | + cdr.begin_serialize_type(current_status, cdr.get_cdr_version() == eprosima::fastcdr::CdrVersion::XCDRv1 |
| 363 | + ? data.enc_xcdrv1 |
| 364 | + : data.enc_xcdrv2); |
| 365 | + cdr << MemberId(0) << data.aval; |
| 366 | + cdr << MemberId(1) << data.bval; |
| 367 | + cdr << MemberId(2) << data.cval; |
| 368 | + cdr.end_serialize_type(current_status); |
| 369 | +} |
| 370 | + |
| 371 | +template<> |
| 372 | +void deserialize( |
| 373 | + Cdr& cdr, |
| 374 | + SizeThreeStruct& data) |
| 375 | +{ |
| 376 | + cdr.deserialize_type(cdr.get_cdr_version() == eprosima::fastcdr::CdrVersion::XCDRv1 |
| 377 | + ? data.enc_xcdrv1 |
| 378 | + : data.enc_xcdrv2, |
| 379 | + [&data](Cdr& cdr_inner, const MemberId& mid) -> bool |
| 380 | + { |
| 381 | + bool ret_value {true}; |
| 382 | + switch (mid.id) |
| 383 | + { |
| 384 | + case 0: |
| 385 | + cdr_inner >> data.aval; |
| 386 | + break; |
| 387 | + case 1: |
| 388 | + cdr_inner >> data.bval; |
| 389 | + break; |
| 390 | + case 2: |
| 391 | + cdr_inner >> data.cval; |
| 392 | + break; |
| 393 | + default: |
| 394 | + ret_value = false; |
| 395 | + break; |
| 396 | + } |
| 397 | + |
| 398 | + return ret_value; |
| 399 | + }); |
| 400 | +} |
| 401 | + |
| 402 | +} // namespace fastcdr |
| 403 | +} // namespace eprosima |
| 404 | + |
279 | 405 | /*! |
280 | 406 | * @test Test a mutable structure where the encoded version has more members that the decoded one. |
281 | 407 | * @code{.idl} |
@@ -1236,6 +1362,139 @@ TEST_P(XCdrMutableTest, inner_appendable_structure) |
1236 | 1362 | //} |
1237 | 1363 | } |
1238 | 1364 |
|
| 1365 | +/*! |
| 1366 | + * @test Test a mutable structure with a field of optional final 3-bytes size struct type. |
| 1367 | + * @code{.idl} |
| 1368 | + * @final |
| 1369 | + * struct SizeThreeStruct |
| 1370 | + * { |
| 1371 | + * octet aval; |
| 1372 | + * octet bval; |
| 1373 | + * octet cval; |
| 1374 | + * }; |
| 1375 | + * |
| 1376 | + * @mutable |
| 1377 | + * struct SizeThreeOptionalStruct |
| 1378 | + * { |
| 1379 | + * @optional SizeThreeStruct opt_val; |
| 1380 | + * }; |
| 1381 | + * @endcode |
| 1382 | + */ |
| 1383 | +TEST_P(XCdrMutableTest, inner_size_three_final_structure) |
| 1384 | +{ |
| 1385 | + constexpr uint8_t aval {0xAA}; |
| 1386 | + constexpr uint8_t bval {0xBB}; |
| 1387 | + constexpr uint8_t cval {0xCC}; |
| 1388 | + |
| 1389 | + //{ Defining expected XCDR streams |
| 1390 | + XCdrStreamValues expected_streams; |
| 1391 | + expected_streams[0 + EncodingAlgorithmFlag::PL_CDR + Cdr::Endianness::BIG_ENDIANNESS] = |
| 1392 | + { |
| 1393 | + 0x00, 0x02, 0x00, 0x00, // Encapsulation |
| 1394 | + 0x00, 0x00, 0x00, 0x03, // ShortMemberHeader |
| 1395 | + aval, bval, cval, // SizeThreeStruct |
| 1396 | + 0x00, // Alignment |
| 1397 | + 0x3F, 0x02, 0x00, 0x00, // Sentinel |
| 1398 | + }; |
| 1399 | + expected_streams[0 + EncodingAlgorithmFlag::PL_CDR + Cdr::Endianness::LITTLE_ENDIANNESS] = |
| 1400 | + { |
| 1401 | + 0x00, 0x03, 0x00, 0x00, // Encapsulation |
| 1402 | + 0x00, 0x00, 0x03, 0x00, // ShortMemberHeader |
| 1403 | + aval, bval, cval, // SizeThreeStruct |
| 1404 | + 0x00, // Alignment |
| 1405 | + 0x02, 0x3F, 0x00, 0x00, // Sentinel |
| 1406 | + }; |
| 1407 | + expected_streams[0 + EncodingAlgorithmFlag::PL_CDR2 + Cdr::Endianness::BIG_ENDIANNESS] = |
| 1408 | + { |
| 1409 | + 0x00, 0x0A, 0x00, 0x01, // Encapsulation |
| 1410 | + 0x00, 0x00, 0x00, 0x0B, // DHEADER |
| 1411 | + 0x40, 0x00, 0x00, 0x00, // EMHEADER1(M) with NEXTINT |
| 1412 | + 0x00, 0x00, 0x00, 0x03, // NEXTINT |
| 1413 | + aval, bval, cval // SizeThreeStruct |
| 1414 | + }; |
| 1415 | + expected_streams[0 + EncodingAlgorithmFlag::PL_CDR2 + Cdr::Endianness::LITTLE_ENDIANNESS] = |
| 1416 | + { |
| 1417 | + 0x00, 0x0B, 0x00, 0x01, // Encapsulation |
| 1418 | + 0x0B, 0x00, 0x00, 0x00, // DHEADER |
| 1419 | + 0x00, 0x00, 0x00, 0x40, // EMHEADER1(M) with NEXTINT |
| 1420 | + 0x03, 0x00, 0x00, 0x00, // NEXTINT |
| 1421 | + aval, bval, cval // SizeThreeStruct |
| 1422 | + }; |
| 1423 | + //} |
| 1424 | + |
| 1425 | + EncodingAlgorithmFlag encoding = std::get<0>(GetParam()); |
| 1426 | + Cdr::Endianness endianness = std::get<1>(GetParam()); |
| 1427 | + SizeThreeStruct value {eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR, |
| 1428 | + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR2, aval, bval, cval}; |
| 1429 | + optional<SizeThreeStruct> opt_value {value}; |
| 1430 | + |
| 1431 | + // Calculate encoded size |
| 1432 | + CdrSizeCalculator calculator(get_version_from_algorithm(encoding)); |
| 1433 | + size_t current_alignment {0}; |
| 1434 | + size_t calculated_size {calculator.begin_calculate_type_serialized_size(encoding, current_alignment)}; |
| 1435 | + calculated_size += calculator.calculate_member_serialized_size(MemberId(0), opt_value, current_alignment); |
| 1436 | + calculated_size += calculator.end_calculate_type_serialized_size(encoding, current_alignment); |
| 1437 | + calculated_size += 4; // Encapsulation |
| 1438 | + //} |
| 1439 | + |
| 1440 | + //{ Prepare buffer |
| 1441 | + uint8_t tested_stream = 0 + encoding + endianness; |
| 1442 | + auto buffer = |
| 1443 | + std::unique_ptr<char, void (*)( |
| 1444 | + void*)>{reinterpret_cast<char*>(calloc(expected_streams[tested_stream].size(), sizeof(char))), free}; |
| 1445 | + FastBuffer fast_buffer(buffer.get(), expected_streams[tested_stream].size()); |
| 1446 | + Cdr cdr(fast_buffer, endianness, get_version_from_algorithm(encoding)); |
| 1447 | + //} |
| 1448 | + |
| 1449 | + //{ Encode |
| 1450 | + cdr.set_encoding_flag(encoding); |
| 1451 | + cdr.serialize_encapsulation(); |
| 1452 | + Cdr::state enc_state(cdr); |
| 1453 | + cdr.begin_serialize_type(enc_state, encoding); |
| 1454 | + cdr << MemberId(0) << opt_value; |
| 1455 | + cdr.end_serialize_type(enc_state); |
| 1456 | + cdr.set_dds_cdr_options({0, 0}); |
| 1457 | + Cdr::state enc_state_end(cdr); |
| 1458 | + //} |
| 1459 | + |
| 1460 | + //{ Test encoded content |
| 1461 | + ASSERT_EQ(cdr.get_serialized_data_length(), expected_streams[tested_stream].size()); |
| 1462 | + ASSERT_EQ(cdr.get_serialized_data_length(), calculated_size); |
| 1463 | + ASSERT_EQ(0, memcmp(buffer.get(), expected_streams[tested_stream].data(), |
| 1464 | + expected_streams[tested_stream].size())); |
| 1465 | + //} |
| 1466 | + |
| 1467 | + //{ Decoding |
| 1468 | + SizeThreeStruct dvalue {eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR, |
| 1469 | + eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR2, aval, bval, cval}; |
| 1470 | + optional<SizeThreeStruct> opt_dvalue {dvalue}; |
| 1471 | + |
| 1472 | + cdr.reset(); |
| 1473 | + cdr.read_encapsulation(); |
| 1474 | + ASSERT_EQ(cdr.get_encoding_flag(), encoding); |
| 1475 | + ASSERT_EQ(cdr.endianness(), endianness); |
| 1476 | + cdr.deserialize_type(encoding, [&](Cdr& cdr_inner, const MemberId& mid)->bool |
| 1477 | + { |
| 1478 | + bool ret_value {true}; |
| 1479 | + |
| 1480 | + switch (mid.id) |
| 1481 | + { |
| 1482 | + case 0: |
| 1483 | + cdr_inner >> opt_dvalue; |
| 1484 | + break; |
| 1485 | + default: |
| 1486 | + ret_value = false; |
| 1487 | + break; |
| 1488 | + } |
| 1489 | + |
| 1490 | + return ret_value; |
| 1491 | + }); |
| 1492 | + ASSERT_EQ(opt_value, opt_dvalue); |
| 1493 | + Cdr::state dec_state_end(cdr); |
| 1494 | + ASSERT_EQ(enc_state_end, dec_state_end); |
| 1495 | + //} |
| 1496 | +} |
| 1497 | + |
1239 | 1498 | INSTANTIATE_TEST_SUITE_P( |
1240 | 1499 | XCdrTest, |
1241 | 1500 | XCdrMutableTest, |
|
0 commit comments