Skip to content

Commit dac7da9

Browse files
mergify[bot]jepemi
andauthored
Fix mutable size-three optional serialization (#253) (#277)
* Refs #23684: Add regression test * Refs #23684: Fix mutable size-three optional serialization * Refs #23684: Uncrustify --------- (cherry picked from commit f00d560) Signed-off-by: Jesus Perez <jesusperez@eprosima.com> Co-authored-by: Jesús Pérez <78275223+jepemi@users.noreply.github.com>
1 parent 42db576 commit dac7da9

File tree

2 files changed

+263
-2
lines changed

2 files changed

+263
-2
lines changed

include/fastcdr/CdrSizeCalculator.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,12 +1245,14 @@ class CdrSizeCalculator
12451245
if (CdrVersion::XCDRv2 == cdr_version_ && EncodingAlgorithmFlag::PL_CDR2 == current_encoding_ &&
12461246
0 < calculated_size)
12471247
{
1248-
if (8 < calculated_size)
1248+
if (8 < calculated_size ||
1249+
(1 != calculated_size && 2 != calculated_size && 4 != calculated_size &&
1250+
8 != calculated_size))
12491251
{
12501252
extra_size = 8; // Long EMHEADER.
12511253
if (NO_SERIALIZED_MEMBER_SIZE != serialized_member_size_)
12521254
{
1253-
extra_size -= 4; // Join NEXTINT and DHEADER.
1255+
calculated_size -= 4; // Join NEXTINT and DHEADER.
12541256
}
12551257
}
12561258
else

test/xcdr/mutable.cpp

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <gtest/gtest.h>
2121

2222
#include <fastcdr/Cdr.h>
23+
#include <fastcdr/CdrSizeCalculator.hpp>
2324
#include "utility.hpp"
2425

2526
using namespace eprosima::fastcdr;
@@ -276,6 +277,131 @@ void deserialize(
276277
} // namespace fastcdr
277278
} // namespace eprosima
278279

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+
279405
/*!
280406
* @test Test a mutable structure where the encoded version has more members that the decoded one.
281407
* @code{.idl}
@@ -1236,6 +1362,139 @@ TEST_P(XCdrMutableTest, inner_appendable_structure)
12361362
//}
12371363
}
12381364

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+
12391498
INSTANTIATE_TEST_SUITE_P(
12401499
XCdrTest,
12411500
XCdrMutableTest,

0 commit comments

Comments
 (0)